mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2026-03-13 11:20:39 +00:00
Pull Stream
This commit is contained in:
@@ -381,7 +381,7 @@ public static class Codec
|
|||||||
ComposeInternal(object valueOrSource, Warehouse warehouse, DistributedConnection connection)
|
ComposeInternal(object valueOrSource, Warehouse warehouse, DistributedConnection connection)
|
||||||
{
|
{
|
||||||
if (valueOrSource == null)
|
if (valueOrSource == null)
|
||||||
return new TDU(TDUIdentifier.Null);
|
return new TDU(TDUIdentifier.Null, null, 0);
|
||||||
|
|
||||||
var type = valueOrSource.GetType();
|
var type = valueOrSource.GetType();
|
||||||
|
|
||||||
@@ -408,7 +408,7 @@ public static class Codec
|
|||||||
valueOrSource = ((IUserType)valueOrSource).Get();
|
valueOrSource = ((IUserType)valueOrSource).Get();
|
||||||
|
|
||||||
if (valueOrSource == null)
|
if (valueOrSource == null)
|
||||||
return new TDU(TDUIdentifier.Null);
|
return new TDU(TDUIdentifier.Null, null, 0);
|
||||||
|
|
||||||
|
|
||||||
type = valueOrSource.GetType();
|
type = valueOrSource.GetType();
|
||||||
@@ -484,7 +484,7 @@ public static class Codec
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TDU(TDUIdentifier.Null);
|
return new TDU(TDUIdentifier.Null, null, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,11 +36,15 @@ using System.Reflection;
|
|||||||
using Esiur.Data;
|
using Esiur.Data;
|
||||||
using Esiur.Core;
|
using Esiur.Core;
|
||||||
using Esiur.Resource;
|
using Esiur.Resource;
|
||||||
|
using System.Collections;
|
||||||
|
using Esiur.Data.GVWIE;
|
||||||
|
|
||||||
namespace Esiur.Data;
|
namespace Esiur.Data;
|
||||||
|
|
||||||
public static class DC // Data Converter
|
public static class DC // Data Converter
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
public static object CastConvert(object value, Type destinationType)
|
public static object CastConvert(object value, Type destinationType)
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Esiur.Core;
|
using Esiur.Core;
|
||||||
using Esiur.Data;
|
using Esiur.Data;
|
||||||
|
using Esiur.Data.GVWIE;
|
||||||
using Esiur.Misc;
|
using Esiur.Misc;
|
||||||
using Esiur.Net.IIP;
|
using Esiur.Net.IIP;
|
||||||
using Esiur.Resource;
|
using Esiur.Resource;
|
||||||
@@ -742,8 +743,8 @@ public static class DataDeserializer
|
|||||||
{
|
{
|
||||||
// get key type
|
// get key type
|
||||||
|
|
||||||
var (keyCs, keyRepType) = RepresentationType.Parse(tdu.Metadata, 0);
|
var (keyCs, keyRepType) = TRU.Parse(tdu.Metadata, 0);
|
||||||
var (valueCs, valueRepType) = RepresentationType.Parse(tdu.Metadata, keyCs);
|
var (valueCs, valueRepType) = TRU.Parse(tdu.Metadata, keyCs);
|
||||||
|
|
||||||
var wh = connection.Instance.Warehouse;
|
var wh = connection.Instance.Warehouse;
|
||||||
|
|
||||||
@@ -792,8 +793,8 @@ public static class DataDeserializer
|
|||||||
{
|
{
|
||||||
// get key type
|
// get key type
|
||||||
|
|
||||||
var (keyCs, keyRepType) = RepresentationType.Parse(tdu.Metadata, 0);
|
var (keyCs, keyRepType) = TRU.Parse(tdu.Metadata, 0);
|
||||||
var (valueCs, valueRepType) = RepresentationType.Parse(tdu.Metadata, keyCs);
|
var (valueCs, valueRepType) = TRU.Parse(tdu.Metadata, keyCs);
|
||||||
|
|
||||||
var map = (IMap)Activator.CreateInstance(typeof(Map<,>).MakeGenericType(keyRepType.GetRuntimeType(warehouse), valueRepType.GetRuntimeType(warehouse)));
|
var map = (IMap)Activator.CreateInstance(typeof(Map<,>).MakeGenericType(keyRepType.GetRuntimeType(warehouse), valueRepType.GetRuntimeType(warehouse)));
|
||||||
|
|
||||||
@@ -838,7 +839,7 @@ public static class DataDeserializer
|
|||||||
uint mtOffset = 1;
|
uint mtOffset = 1;
|
||||||
for (var i = 0; i < tupleSize; i++)
|
for (var i = 0; i < tupleSize; i++)
|
||||||
{
|
{
|
||||||
var (cs, rep) = RepresentationType.Parse(tdu.Metadata, mtOffset);
|
var (cs, rep) = TRU.Parse(tdu.Metadata, mtOffset);
|
||||||
types.Add(rep.GetRuntimeType(connection.Instance.Warehouse));
|
types.Add(rep.GetRuntimeType(connection.Instance.Warehouse));
|
||||||
mtOffset += cs;
|
mtOffset += cs;
|
||||||
}
|
}
|
||||||
@@ -913,7 +914,7 @@ public static class DataDeserializer
|
|||||||
uint mtOffset = 1;
|
uint mtOffset = 1;
|
||||||
for (var i = 0; i < tupleSize; i++)
|
for (var i = 0; i < tupleSize; i++)
|
||||||
{
|
{
|
||||||
var (cs, rep) = RepresentationType.Parse(tdu.Metadata, mtOffset);
|
var (cs, rep) = TRU.Parse(tdu.Metadata, mtOffset);
|
||||||
types.Add(rep.GetRuntimeType(warehouse));
|
types.Add(rep.GetRuntimeType(warehouse));
|
||||||
mtOffset += cs;
|
mtOffset += cs;
|
||||||
}
|
}
|
||||||
@@ -975,111 +976,152 @@ public static class DataDeserializer
|
|||||||
|
|
||||||
public static AsyncReply TypedListParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
|
public static AsyncReply TypedListParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
|
||||||
{
|
{
|
||||||
var rt = new AsyncBag<object>();
|
|
||||||
|
|
||||||
// get the type
|
// get the type
|
||||||
var (hdrCs, rep) = RepresentationType.Parse(tdu.Metadata, 0);
|
var (hdrCs, rep) = TRU.Parse(tdu.Metadata, 0);
|
||||||
|
|
||||||
|
switch (rep.Identifier)
|
||||||
var runtimeType = rep.GetRuntimeType(connection.Instance.Warehouse);
|
|
||||||
|
|
||||||
rt.ArrayType = runtimeType;
|
|
||||||
|
|
||||||
ParsedTDU current;
|
|
||||||
ParsedTDU? previous = null;
|
|
||||||
|
|
||||||
var offset = tdu.Offset;
|
|
||||||
var length = tdu.ContentLength;
|
|
||||||
var ends = offset + (uint)length;
|
|
||||||
|
|
||||||
while (length > 0)
|
|
||||||
{
|
{
|
||||||
|
case TRUIdentifier.Int32:
|
||||||
|
return new AsyncReply(GroupInt32Codec.Decode(tdu.Data.AsSpan(
|
||||||
|
(int)tdu.Offset, (int)tdu.ContentLength)));
|
||||||
|
case TRUIdentifier.Int64:
|
||||||
|
return new AsyncReply(GroupInt64Codec.Decode(tdu.Data.AsSpan(
|
||||||
|
(int)tdu.Offset, (int)tdu.ContentLength)));
|
||||||
|
case TRUIdentifier.Int16:
|
||||||
|
return new AsyncReply(GroupInt16Codec.Decode(tdu.Data.AsSpan(
|
||||||
|
(int)tdu.Offset, (int)tdu.ContentLength)));
|
||||||
|
case TRUIdentifier.UInt32:
|
||||||
|
return new AsyncReply(GroupUInt32Codec.Decode(tdu.Data.AsSpan(
|
||||||
|
(int)tdu.Offset, (int)tdu.ContentLength)));
|
||||||
|
case TRUIdentifier.UInt64:
|
||||||
|
return new AsyncReply(GroupUInt64Codec.Decode(tdu.Data.AsSpan(
|
||||||
|
(int)tdu.Offset, (int)tdu.ContentLength)));
|
||||||
|
case TRUIdentifier.UInt16:
|
||||||
|
return new AsyncReply(GroupUInt16Codec.Decode(tdu.Data.AsSpan(
|
||||||
|
(int)tdu.Offset, (int)tdu.ContentLength)));
|
||||||
|
default:
|
||||||
|
|
||||||
current = ParsedTDU.Parse(tdu.Data, offset, ends);
|
var rt = new AsyncBag<object>();
|
||||||
|
|
||||||
if (current.Class == TDUClass.Invalid)
|
var runtimeType = rep.GetRuntimeType(connection.Instance.Warehouse);
|
||||||
throw new Exception("Unknown type.");
|
|
||||||
|
rt.ArrayType = runtimeType;
|
||||||
|
|
||||||
|
ParsedTDU current;
|
||||||
|
ParsedTDU? previous = null;
|
||||||
|
|
||||||
|
var offset = tdu.Offset;
|
||||||
|
var length = tdu.ContentLength;
|
||||||
|
var ends = offset + (uint)length;
|
||||||
|
|
||||||
|
while (length > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
current = ParsedTDU.Parse(tdu.Data, offset, ends);
|
||||||
|
|
||||||
|
if (current.Class == TDUClass.Invalid)
|
||||||
|
throw new Exception("Unknown type.");
|
||||||
|
|
||||||
|
|
||||||
if (current.Identifier == TDUIdentifier.TypeContinuation)
|
if (current.Identifier == TDUIdentifier.TypeContinuation)
|
||||||
{
|
{
|
||||||
current.Class = previous.Value.Class;
|
current.Class = previous.Value.Class;
|
||||||
current.Identifier = previous.Value.Identifier;
|
current.Identifier = previous.Value.Identifier;
|
||||||
current.Metadata = previous.Value.Metadata;
|
current.Metadata = previous.Value.Metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
var (cs, reply) = Codec.ParseAsync(tdu.Data, offset, connection, requestSequence);
|
var (cs, reply) = Codec.ParseAsync(tdu.Data, offset, connection, requestSequence);
|
||||||
|
|
||||||
rt.Add(reply);
|
rt.Add(reply);
|
||||||
|
|
||||||
if (cs > 0)
|
if (cs > 0)
|
||||||
{
|
{
|
||||||
offset += (uint)cs;
|
offset += (uint)cs;
|
||||||
length -= (uint)cs;
|
length -= (uint)cs;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw new Exception("Error while parsing structured data");
|
throw new Exception("Error while parsing structured data");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
rt.Seal();
|
||||||
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
rt.Seal();
|
|
||||||
return rt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static object TypedListParser(ParsedTDU tdu, Warehouse warehouse)
|
public static object TypedListParser(ParsedTDU tdu, Warehouse warehouse)
|
||||||
{
|
{
|
||||||
|
|
||||||
// get the type
|
// get the type
|
||||||
var (hdrCs, rep) = RepresentationType.Parse(tdu.Metadata, 0);
|
var (hdrCs, rep) = TRU.Parse(tdu.Metadata, 0);
|
||||||
|
|
||||||
//offset += hdrCs;
|
switch (rep.Identifier)
|
||||||
//length -= hdrCs;
|
|
||||||
|
|
||||||
var runtimeType = rep.GetRuntimeType(warehouse);
|
|
||||||
|
|
||||||
var list = new List<object>();
|
|
||||||
|
|
||||||
ParsedTDU current;
|
|
||||||
ParsedTDU? previous = null;
|
|
||||||
|
|
||||||
var offset = tdu.Offset;
|
|
||||||
var length = tdu.ContentLength;
|
|
||||||
var ends = offset + (uint)length;
|
|
||||||
|
|
||||||
while (length > 0)
|
|
||||||
{
|
{
|
||||||
current = ParsedTDU.Parse(tdu.Data, offset, ends);
|
case TRUIdentifier.Int32:
|
||||||
|
return GroupInt32Codec.Decode(tdu.Data.AsSpan(
|
||||||
if (current.Class == TDUClass.Invalid)
|
(int)tdu.Offset, (int)tdu.ContentLength));
|
||||||
throw new Exception("Unknown type.");
|
case TRUIdentifier.Int64:
|
||||||
|
return GroupInt64Codec.Decode(tdu.Data.AsSpan(
|
||||||
|
(int)tdu.Offset, (int)tdu.ContentLength));
|
||||||
|
case TRUIdentifier.Int16:
|
||||||
|
return GroupInt16Codec.Decode(tdu.Data.AsSpan(
|
||||||
|
(int)tdu.Offset, (int)tdu.ContentLength));
|
||||||
|
case TRUIdentifier.UInt32:
|
||||||
|
return GroupUInt32Codec.Decode(tdu.Data.AsSpan(
|
||||||
|
(int)tdu.Offset, (int)tdu.ContentLength));
|
||||||
|
case TRUIdentifier.UInt64:
|
||||||
|
return GroupUInt64Codec.Decode(tdu.Data.AsSpan(
|
||||||
|
(int)tdu.Offset, (int)tdu.ContentLength));
|
||||||
|
case TRUIdentifier.UInt16:
|
||||||
|
return GroupUInt16Codec.Decode(tdu.Data.AsSpan(
|
||||||
|
(int)tdu.Offset, (int)tdu.ContentLength));
|
||||||
|
default:
|
||||||
|
|
||||||
|
|
||||||
if (current.Identifier == TDUIdentifier.TypeContinuation)
|
var list = new List<object>();
|
||||||
{
|
|
||||||
current.Class = previous.Value.Class;
|
|
||||||
current.Identifier = previous.Value.Identifier;
|
|
||||||
current.Metadata = previous.Value.Metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
var (cs, reply) = Codec.ParseSync(current, warehouse);
|
ParsedTDU current;
|
||||||
|
ParsedTDU? previous = null;
|
||||||
|
|
||||||
list.Add(reply);
|
var offset = tdu.Offset;
|
||||||
|
var length = tdu.ContentLength;
|
||||||
|
var ends = offset + (uint)length;
|
||||||
|
|
||||||
if (cs > 0)
|
while (length > 0)
|
||||||
{
|
{
|
||||||
offset += (uint)cs;
|
current = ParsedTDU.Parse(tdu.Data, offset, ends);
|
||||||
length -= (uint)cs;
|
|
||||||
previous = current;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw new Exception("Error while parsing structured data");
|
|
||||||
|
|
||||||
|
if (current.Class == TDUClass.Invalid)
|
||||||
|
throw new Exception("Unknown type.");
|
||||||
|
|
||||||
|
|
||||||
|
if (current.Identifier == TDUIdentifier.TypeContinuation)
|
||||||
|
{
|
||||||
|
current.Class = previous.Value.Class;
|
||||||
|
current.Identifier = previous.Value.Identifier;
|
||||||
|
current.Metadata = previous.Value.Metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
var (cs, reply) = Codec.ParseSync(current, warehouse);
|
||||||
|
|
||||||
|
list.Add(reply);
|
||||||
|
|
||||||
|
if (cs > 0)
|
||||||
|
{
|
||||||
|
offset += (uint)cs;
|
||||||
|
length -= (uint)cs;
|
||||||
|
previous = current;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new Exception("Error while parsing structured data");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var runtimeType = rep.GetRuntimeType(warehouse);
|
||||||
|
var rt = Array.CreateInstance(runtimeType, list.Count);
|
||||||
|
Array.Copy(list.ToArray(), rt, rt.Length);
|
||||||
|
|
||||||
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rt = Array.CreateInstance(runtimeType, list.Count);
|
|
||||||
Array.Copy(list.ToArray(), rt, rt.Length);
|
|
||||||
|
|
||||||
return rt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsyncBag<PropertyValue> PropertyValueArrayParserAsync(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)//, bool ageIncluded = true)
|
public static AsyncBag<PropertyValue> PropertyValueArrayParserAsync(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)//, bool ageIncluded = true)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Esiur.Core;
|
using Esiur.Core;
|
||||||
|
using Esiur.Data.GVWIE;
|
||||||
using Esiur.Net.IIP;
|
using Esiur.Net.IIP;
|
||||||
using Esiur.Resource;
|
using Esiur.Resource;
|
||||||
using Esiur.Resource.Template;
|
using Esiur.Resource.Template;
|
||||||
@@ -112,7 +113,7 @@ public static class DataSerializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static unsafe TDU Float32Composer(object value, Warehouse warehouse, DistributedConnection connection)
|
public static unsafe TDU Float32Composer(object value, Warehouse warehouse, DistributedConnection connection)
|
||||||
{
|
{
|
||||||
float v = (float)value;
|
float v = (float)value;
|
||||||
|
|
||||||
@@ -404,6 +405,7 @@ public static class DataSerializer
|
|||||||
if (ct == null)
|
if (ct == null)
|
||||||
return new TDU(TDUIdentifier.Null, null, 0);
|
return new TDU(TDUIdentifier.Null, null, 0);
|
||||||
|
|
||||||
|
return Codec.ComposeInternal(intVal, warehouse, connection);
|
||||||
|
|
||||||
return new TDU(TDUIdentifier.TypedEnum,
|
return new TDU(TDUIdentifier.TypedEnum,
|
||||||
new byte[] { ct.Index }, 1, template.ClassId.Data);
|
new byte[] { ct.Index }, 1, template.ClassId.Data);
|
||||||
@@ -442,18 +444,18 @@ public static class DataSerializer
|
|||||||
{
|
{
|
||||||
if ((bool)value)
|
if ((bool)value)
|
||||||
{
|
{
|
||||||
return new TDU(TDUIdentifier.True);
|
return new TDU(TDUIdentifier.True, null, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new TDU(TDUIdentifier.True);
|
return new TDU(TDUIdentifier.True, null, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static TDU NotModifiedComposer(object value, Warehouse warehouse, DistributedConnection connection)
|
public static TDU NotModifiedComposer(object value, Warehouse warehouse, DistributedConnection connection)
|
||||||
{
|
{
|
||||||
return new TDU(TDUIdentifier.NotModified);
|
return new TDU(TDUIdentifier.NotModified, null, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TDU RawDataComposerFromArray(object value, Warehouse warehouse, DistributedConnection connection)
|
public static TDU RawDataComposerFromArray(object value, Warehouse warehouse, DistributedConnection connection)
|
||||||
@@ -492,16 +494,85 @@ public static class DataSerializer
|
|||||||
|
|
||||||
public static TDU TypedListComposer(IEnumerable value, Type type, Warehouse warehouse, DistributedConnection connection)
|
public static TDU TypedListComposer(IEnumerable value, Type type, Warehouse warehouse, DistributedConnection connection)
|
||||||
{
|
{
|
||||||
var composed = ArrayComposer((IEnumerable)value, warehouse, connection);
|
byte[] composed;
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return new TDU(TDUIdentifier.Null, new byte[0], 0);
|
||||||
|
|
||||||
|
var tru = TRU.FromType(type);
|
||||||
|
|
||||||
|
if (type == typeof(int))
|
||||||
|
{
|
||||||
|
composed = GroupInt32Codec.Encode((IList<int>)value);
|
||||||
|
}
|
||||||
|
else if (type == typeof(long))
|
||||||
|
{
|
||||||
|
composed = GroupInt64Codec.Encode((IList<long>)value);
|
||||||
|
}
|
||||||
|
else if (type == typeof(short))
|
||||||
|
{
|
||||||
|
composed = GroupInt16Codec.Encode((IList<short>)value);
|
||||||
|
}
|
||||||
|
else if (type == typeof(uint))
|
||||||
|
{
|
||||||
|
composed = GroupUInt32Codec.Encode((IList<uint>)value);
|
||||||
|
}
|
||||||
|
else if (type == typeof(ulong))
|
||||||
|
{
|
||||||
|
composed = GroupUInt64Codec.Encode((IList<ulong>)value);
|
||||||
|
}
|
||||||
|
else if (type == typeof(ushort))
|
||||||
|
{
|
||||||
|
composed = GroupUInt16Codec.Encode((IList<ushort>)value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var rt = new List<byte>();
|
||||||
|
|
||||||
|
TDU? previous = null;
|
||||||
|
|
||||||
|
foreach (var i in value)
|
||||||
|
{
|
||||||
|
var tdu = Codec.ComposeInternal(i, warehouse, connection);
|
||||||
|
|
||||||
|
var currentTru = TRU.FromType(i.GetType());
|
||||||
|
|
||||||
|
if (tru.Match(currentTru))
|
||||||
|
{
|
||||||
|
var d = tdu.Composed.Clip(tdu.ContentOffset,
|
||||||
|
(uint)tdu.Composed.Length - tdu.ContentOffset);
|
||||||
|
|
||||||
|
var ntd = new TDU(TDUIdentifier.TypeOfTarget, d, (ulong)d.Length);
|
||||||
|
rt.AddRange(ntd.Composed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
if (previous != null && tdu.MatchType(previous.Value))
|
||||||
|
{
|
||||||
|
var d = tdu.Composed.Clip(tdu.ContentOffset,
|
||||||
|
(uint)tdu.Composed.Length - tdu.ContentOffset);
|
||||||
|
|
||||||
|
var ntd = new TDU(TDUIdentifier.TypeContinuation, d, (ulong)d.Length);
|
||||||
|
rt.AddRange(ntd.Composed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt.AddRange(tdu.Composed);
|
||||||
|
}
|
||||||
|
|
||||||
|
previous = tdu;
|
||||||
|
}
|
||||||
|
|
||||||
|
composed = rt.ToArray();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (composed == null)
|
if (composed == null)
|
||||||
return new TDU(TDUIdentifier.Null, new byte[0], 0);
|
return new TDU(TDUIdentifier.Null, new byte[0], 0);
|
||||||
|
|
||||||
var metadata = RepresentationType.FromType(type).Compose();
|
var metadata = tru.Compose();
|
||||||
|
|
||||||
|
return new TDU(TDUIdentifier.TypedList, composed, (uint)composed.Length, metadata);
|
||||||
return new TDU(TDUIdentifier.TypedList, composed,
|
|
||||||
(uint)composed.Length, metadata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//public static byte[] PropertyValueComposer(PropertyValue propertyValue, DistributedConnection connection)//, bool includeAge = true)
|
//public static byte[] PropertyValueComposer(PropertyValue propertyValue, DistributedConnection connection)//, bool includeAge = true)
|
||||||
@@ -539,8 +610,8 @@ public static class DataSerializer
|
|||||||
if (value == null)
|
if (value == null)
|
||||||
return new TDU(TDUIdentifier.Null, new byte[0], 0);
|
return new TDU(TDUIdentifier.Null, new byte[0], 0);
|
||||||
|
|
||||||
var kt = RepresentationType.FromType(keyType).Compose();
|
var kt = TRU.FromType(keyType).Compose();
|
||||||
var vt = RepresentationType.FromType(valueType).Compose();
|
var vt = TRU.FromType(valueType).Compose();
|
||||||
|
|
||||||
var rt = new List<byte>();
|
var rt = new List<byte>();
|
||||||
|
|
||||||
@@ -558,8 +629,8 @@ public static class DataSerializer
|
|||||||
if (value == null)
|
if (value == null)
|
||||||
return new TDU(TDUIdentifier.Null, null, 0);
|
return new TDU(TDUIdentifier.Null, null, 0);
|
||||||
|
|
||||||
var kt = RepresentationType.FromType(keyType).Compose();
|
var kt = TRU.FromType(keyType).Compose();
|
||||||
var vt = RepresentationType.FromType(valueType).Compose();
|
var vt = TRU.FromType(valueType).Compose();
|
||||||
|
|
||||||
var rt = new List<byte>();
|
var rt = new List<byte>();
|
||||||
|
|
||||||
@@ -583,7 +654,7 @@ public static class DataSerializer
|
|||||||
DC.Combine(kt, 0, (uint)kt.Length, vt, 0, (uint)vt.Length));
|
DC.Combine(kt, 0, (uint)kt.Length, vt, 0, (uint)vt.Length));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] ArrayComposer(IEnumerable value, Warehouse warehouse, DistributedConnection connection)
|
public static byte[] DynamicArrayComposer(IEnumerable value, Warehouse warehouse, DistributedConnection connection)
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
return null;
|
return null;
|
||||||
@@ -727,14 +798,29 @@ public static class DataSerializer
|
|||||||
foreach (var pt in template.Properties)
|
foreach (var pt in template.Properties)
|
||||||
{
|
{
|
||||||
var propValue = pt.PropertyInfo.GetValue(record, null);
|
var propValue = pt.PropertyInfo.GetValue(record, null);
|
||||||
var rr = Codec.Compose(propValue, warehouse, connection);
|
|
||||||
rt.AddRange(rr);
|
if (propValue == null)
|
||||||
|
return new TDU(TDUIdentifier.Null, null, 0);
|
||||||
|
var tru = TRU.FromType(propValue.GetType());
|
||||||
|
var tdu = Codec.ComposeInternal(propValue, warehouse, connection);
|
||||||
|
|
||||||
|
|
||||||
|
if (pt.ValueType.Identifier == TRUIdentifier.TypedRecord && pt.ValueType.Match(tru))
|
||||||
|
{
|
||||||
|
// strip metadata
|
||||||
|
var len = (uint)tdu.Composed.Length - tdu.ContentOffset;
|
||||||
|
tdu = new TDU(TDUIdentifier.TypeOfTarget,
|
||||||
|
tdu.Composed.Clip(tdu.ContentOffset, len), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt.AddRange(tdu.Composed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TDU(TDUIdentifier.Record, rt.ToArray(),
|
return new TDU(TDUIdentifier.Record, rt.ToArray(),
|
||||||
(uint)rt.Count,
|
(uint)rt.Count,
|
||||||
template.ClassId.Data);
|
template.ClassId.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] HistoryComposer(KeyList<PropertyTemplate, PropertyValue[]> history, Warehouse warehouse,
|
public static byte[] HistoryComposer(KeyList<PropertyTemplate, PropertyValue[]> history, Warehouse warehouse,
|
||||||
DistributedConnection connection, bool prependLength = false)
|
DistributedConnection connection, bool prependLength = false)
|
||||||
{
|
{
|
||||||
@@ -758,7 +844,7 @@ public static class DataSerializer
|
|||||||
|
|
||||||
var fields = value.GetType().GetFields();
|
var fields = value.GetType().GetFields();
|
||||||
var list = fields.Select(x => x.GetValue(value)).ToArray();
|
var list = fields.Select(x => x.GetValue(value)).ToArray();
|
||||||
var types = fields.Select(x => RepresentationType.FromType(x.FieldType).Compose()).ToArray();
|
var types = fields.Select(x => TRU.FromType(x.FieldType).Compose()).ToArray();
|
||||||
|
|
||||||
|
|
||||||
var metadata = new List<byte>();
|
var metadata = new List<byte>();
|
||||||
|
|||||||
137
Esiur/Data/GVWIE/GroupInt16Codec.cs
Normal file
137
Esiur/Data/GVWIE/GroupInt16Codec.cs
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Esiur.Data.GVWIE;
|
||||||
|
|
||||||
|
public static class GroupInt16Codec
|
||||||
|
{
|
||||||
|
// ----------------- Encoder -----------------
|
||||||
|
public static byte[] Encode(IList<short> values)
|
||||||
|
{
|
||||||
|
var dst = new List<byte>(values.Count); // close lower bound
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (i < values.Count)
|
||||||
|
{
|
||||||
|
ushort zz = ZigZag16(values[i]);
|
||||||
|
|
||||||
|
// Fast path: single byte with 7-bit ZigZag
|
||||||
|
if (zz <= 0x7Fu)
|
||||||
|
{
|
||||||
|
dst.Add((byte)zz); // MSB=0 implicitly
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group path: up to 64 items sharing width (1 or 2 bytes)
|
||||||
|
int start = i;
|
||||||
|
int count = 1;
|
||||||
|
int width = (zz <= 0xFFu) ? 1 : 2;
|
||||||
|
|
||||||
|
while (count < 64 && (i + count) < values.Count)
|
||||||
|
{
|
||||||
|
ushort z2 = ZigZag16(values[i + count]);
|
||||||
|
int w2 = (z2 <= 0xFFu) ? 1 : 2;
|
||||||
|
if (w2 > width) width = w2; // widen as needed
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header: 1 | (count-1)[6 bits] | (width-1)[1 bit]
|
||||||
|
byte header = 0x80;
|
||||||
|
header |= (byte)(((count - 1) & 0x3F) << 1);
|
||||||
|
header |= (byte)((width - 1) & 0x01);
|
||||||
|
dst.Add(header);
|
||||||
|
|
||||||
|
// Payload: count ZigZag magnitudes, LE, 'width' bytes each
|
||||||
|
for (int k = 0; k < count; k++)
|
||||||
|
{
|
||||||
|
ushort z = ZigZag16(values[start + k]);
|
||||||
|
WriteLE(dst, z, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
i += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Decoder -----------------
|
||||||
|
public static short[] Decode(ReadOnlySpan<byte> src)
|
||||||
|
{
|
||||||
|
var result = new List<short>();
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
while (pos < src.Length)
|
||||||
|
{
|
||||||
|
byte h = src[pos++];
|
||||||
|
|
||||||
|
if ((h & 0x80) == 0)
|
||||||
|
{
|
||||||
|
// Fast path: 7-bit ZigZag
|
||||||
|
ushort zz7 = (ushort)(h & 0x7F);
|
||||||
|
result.Add(UnZigZag16(zz7));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = ((h >> 1) & 0x3F) + 1; // 1..64
|
||||||
|
int width = (h & 0x01) + 1; // 1..2
|
||||||
|
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
uint raw = ReadLE(src, ref pos, width);
|
||||||
|
if (width > 2 && (raw >> 16) != 0)
|
||||||
|
throw new OverflowException("Decoded ZigZag value exceeds 16-bit range.");
|
||||||
|
|
||||||
|
ushort u = (ushort)raw;
|
||||||
|
short val = UnZigZag16(u);
|
||||||
|
result.Add(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Helpers -----------------
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static ushort ZigZag16(short v)
|
||||||
|
{
|
||||||
|
// (v << 1) ^ (v >> 15), result as unsigned 16-bit
|
||||||
|
return (ushort)(((uint)(ushort)v << 1) ^ (uint)((int)v >> 15));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static short UnZigZag16(ushort u)
|
||||||
|
{
|
||||||
|
// (u >> 1) ^ -(u & 1), narrowed to 16-bit signed
|
||||||
|
return (short)((u >> 1) ^ (ushort)-(short)(u & 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static void WriteLE(List<byte> dst, ushort value, int width)
|
||||||
|
{
|
||||||
|
// width is 1 or 2
|
||||||
|
dst.Add((byte)(value & 0xFF));
|
||||||
|
if (width == 2) dst.Add((byte)(value >> 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static uint ReadLE(ReadOnlySpan<byte> src, ref int pos, int width)
|
||||||
|
{
|
||||||
|
if ((uint)(pos + width) > (uint)src.Length)
|
||||||
|
throw new ArgumentException("Buffer underflow while reading group payload.");
|
||||||
|
|
||||||
|
uint v = src[pos++];
|
||||||
|
if (width == 2)
|
||||||
|
{
|
||||||
|
v |= (uint)src[pos++] << 8;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
129
Esiur/Data/GVWIE/GroupInt32Codec.cs
Normal file
129
Esiur/Data/GVWIE/GroupInt32Codec.cs
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace Esiur.Data.GVWIE;
|
||||||
|
|
||||||
|
public static class GroupInt32Codec
|
||||||
|
{
|
||||||
|
// ----------------- Encoder -----------------
|
||||||
|
public static byte[] Encode(IList<int> values)
|
||||||
|
{
|
||||||
|
//var values = value as int[];
|
||||||
|
|
||||||
|
var dst = new List<byte>(values.Count * 2);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (i < values.Count)
|
||||||
|
{
|
||||||
|
uint zz = ZigZag32(values[i]);
|
||||||
|
|
||||||
|
// Fast path: single byte (MSB=0) when zigzag fits in 7 bits
|
||||||
|
if (zz <= 0x7Fu)
|
||||||
|
{
|
||||||
|
dst.Add((byte)zz);
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group: up to 32 items sharing a common width (1..4 bytes)
|
||||||
|
int start = i;
|
||||||
|
int count = 1;
|
||||||
|
int width = WidthFromZigZag(zz);
|
||||||
|
|
||||||
|
while (count < 32 && (i + count) < values.Count)
|
||||||
|
{
|
||||||
|
uint z2 = ZigZag32(values[i + count]);
|
||||||
|
int w2 = WidthFromZigZag(z2);
|
||||||
|
width = Math.Max(width, w2); // widen as needed
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header: 1 | (count-1)[5 bits] | (width-1)[2 bits]
|
||||||
|
byte header = 0x80;
|
||||||
|
header |= (byte)(((count - 1) & 0x1F) << 2);
|
||||||
|
header |= (byte)((width - 1) & 0x03);
|
||||||
|
dst.Add(header);
|
||||||
|
|
||||||
|
// Payload: 'count' zigzag values, LE, 'width' bytes each
|
||||||
|
for (int k = 0; k < count; k++)
|
||||||
|
WriteLE(dst, ZigZag32(values[start + k]), width);
|
||||||
|
|
||||||
|
i += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Decoder -----------------
|
||||||
|
public static int[] Decode(ReadOnlySpan<byte> src)
|
||||||
|
{
|
||||||
|
var result = new List<int>();
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
while (pos < src.Length)
|
||||||
|
{
|
||||||
|
byte h = src[pos++];
|
||||||
|
|
||||||
|
if ((h & 0x80) == 0)
|
||||||
|
{
|
||||||
|
// Fast path: 7-bit ZigZag in low bits
|
||||||
|
uint zz7 = (uint)(h & 0x7F);
|
||||||
|
result.Add(UnZigZag32(zz7));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = ((h >> 2) & 0x1F) + 1; // 1..32
|
||||||
|
int width = (h & 0x03) + 1; // 1..4
|
||||||
|
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
uint raw = (uint)ReadLE(src, ref pos, width);
|
||||||
|
int val = UnZigZag32(raw);
|
||||||
|
result.Add(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Helpers -----------------
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static uint ZigZag32(int v) => (uint)((v << 1) ^ (v >> 31));
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static int UnZigZag32(uint u) => (int)((u >> 1) ^ (uint)-(int)(u & 1));
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static int WidthFromZigZag(uint z)
|
||||||
|
{
|
||||||
|
if (z <= 0xFFu) return 1;
|
||||||
|
if (z <= 0xFFFFu) return 2;
|
||||||
|
if (z <= 0xFFFFFFu) return 3;
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static void WriteLE(List<byte> dst, uint value, int width)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
dst.Add((byte)((value >> (8 * i)) & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static ulong ReadLE(ReadOnlySpan<byte> src, ref int pos, int width)
|
||||||
|
{
|
||||||
|
if ((uint)(pos + width) > (uint)src.Length)
|
||||||
|
throw new ArgumentException("Buffer underflow while reading group payload.");
|
||||||
|
|
||||||
|
ulong v = 0;
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
v |= (ulong)src[pos++] << (8 * i);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
135
Esiur/Data/GVWIE/GroupInt64Codec.cs
Normal file
135
Esiur/Data/GVWIE/GroupInt64Codec.cs
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Esiur.Data.GVWIE;
|
||||||
|
|
||||||
|
public static class GroupInt64Codec
|
||||||
|
{
|
||||||
|
// ----------------- Encoder -----------------
|
||||||
|
public static byte[] Encode(IList<long> values)
|
||||||
|
{
|
||||||
|
var dst = new List<byte>(values.Count * 2);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (i < values.Count)
|
||||||
|
{
|
||||||
|
ulong zz = ZigZag64(values[i]);
|
||||||
|
|
||||||
|
// Fast path: 1 byte when ZigZag fits in 7 bits
|
||||||
|
if (zz <= 0x7Ful)
|
||||||
|
{
|
||||||
|
dst.Add((byte)zz); // MSB = 0 implicitly
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group path: up to 16 items sharing a common width (1..8 bytes)
|
||||||
|
int start = i;
|
||||||
|
int count = 1;
|
||||||
|
int width = WidthFromZigZag(zz);
|
||||||
|
|
||||||
|
while (count < 16 && (i + count) < values.Count)
|
||||||
|
{
|
||||||
|
ulong z2 = ZigZag64(values[i + count]);
|
||||||
|
int w2 = WidthFromZigZag(z2);
|
||||||
|
width = Math.Max(width, w2); // widen as needed
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header: 1 | (count-1)[4 bits] | (width-1)[3 bits]
|
||||||
|
byte header = 0x80;
|
||||||
|
header |= (byte)(((count - 1) & 0x0F) << 3);
|
||||||
|
header |= (byte)((width - 1) & 0x07);
|
||||||
|
dst.Add(header);
|
||||||
|
|
||||||
|
// Payload: 'count' ZigZag values, LE, 'width' bytes each
|
||||||
|
for (int k = 0; k < count; k++)
|
||||||
|
{
|
||||||
|
ulong z = ZigZag64(values[start + k]);
|
||||||
|
WriteLE(dst, z, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
i += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Decoder -----------------
|
||||||
|
public static long[] Decode(ReadOnlySpan<byte> src)
|
||||||
|
{
|
||||||
|
var result = new List<long>();
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
while (pos < src.Length)
|
||||||
|
{
|
||||||
|
byte h = src[pos++];
|
||||||
|
|
||||||
|
if ((h & 0x80) == 0)
|
||||||
|
{
|
||||||
|
// Fast path: 7-bit ZigZag
|
||||||
|
ulong zz7 = (ulong)(h & 0x7F);
|
||||||
|
result.Add(UnZigZag64(zz7));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = ((h >> 3) & 0x0F) + 1; // 1..16
|
||||||
|
int width = (h & 0x07) + 1; // 1..8
|
||||||
|
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
ulong raw = ReadLE(src, ref pos, width);
|
||||||
|
long val = UnZigZag64(raw);
|
||||||
|
result.Add(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Helpers -----------------
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static ulong ZigZag64(long v) => (ulong)((v << 1) ^ (v >> 63));
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static long UnZigZag64(ulong u) => (long)((u >> 1) ^ (ulong)-(long)(u & 1));
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static int WidthFromZigZag(ulong z)
|
||||||
|
{
|
||||||
|
if (z <= 0xFFUL) return 1;
|
||||||
|
if (z <= 0xFFFFUL) return 2;
|
||||||
|
if (z <= 0xFFFFFFUL) return 3;
|
||||||
|
if (z <= 0xFFFFFFFFUL) return 4;
|
||||||
|
if (z <= 0xFFFFFFFFFFUL) return 5;
|
||||||
|
if (z <= 0xFFFFFFFFFFFFUL) return 6;
|
||||||
|
if (z <= 0xFFFFFFFFFFFFFFUL) return 7;
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static void WriteLE(List<byte> dst, ulong value, int width)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
dst.Add((byte)((value >> (8 * i)) & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static ulong ReadLE(ReadOnlySpan<byte> src, ref int pos, int width)
|
||||||
|
{
|
||||||
|
if ((uint)(pos + width) > (uint)src.Length)
|
||||||
|
throw new ArgumentException("Buffer underflow while reading group payload.");
|
||||||
|
|
||||||
|
ulong v = 0;
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
v |= (ulong)src[pos++] << (8 * i);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
121
Esiur/Data/GVWIE/GroupUInt16Codec.cs
Normal file
121
Esiur/Data/GVWIE/GroupUInt16Codec.cs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Esiur.Data.GVWIE;
|
||||||
|
|
||||||
|
|
||||||
|
public static class GroupUInt16Codec
|
||||||
|
{
|
||||||
|
// ----------------- Encoder -----------------
|
||||||
|
public static byte[] Encode(IList<ushort> values)
|
||||||
|
{
|
||||||
|
if (values is null) throw new ArgumentNullException(nameof(values));
|
||||||
|
|
||||||
|
var dst = new List<byte>(values.Count * 2);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (i < values.Count)
|
||||||
|
{
|
||||||
|
ushort v = values[i];
|
||||||
|
|
||||||
|
// Fast path: single byte for 0..127
|
||||||
|
if (v <= 0x7F)
|
||||||
|
{
|
||||||
|
dst.Add((byte)v); // MSB=0 implicitly
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group path: up to 16 items sharing a common width (1..2 bytes for uint16)
|
||||||
|
int start = i;
|
||||||
|
int count = 1;
|
||||||
|
int width = WidthFromUnsigned(v);
|
||||||
|
|
||||||
|
while (count < 16 && (i + count) < values.Count)
|
||||||
|
{
|
||||||
|
ushort v2 = values[i + count];
|
||||||
|
int w2 = WidthFromUnsigned(v2);
|
||||||
|
if (w2 > width) width = w2; // widen group if needed
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header: 1 | (count-1)[4b] | (width-1)[3b]
|
||||||
|
byte header = 0x80;
|
||||||
|
header |= (byte)(((count - 1) & 0xF) << 3);
|
||||||
|
header |= (byte)((width - 1) & 0x7);
|
||||||
|
dst.Add(header);
|
||||||
|
|
||||||
|
// Payload
|
||||||
|
for (int k = 0; k < count; k++)
|
||||||
|
{
|
||||||
|
WriteLE(dst, values[start + k], width);
|
||||||
|
}
|
||||||
|
|
||||||
|
i += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Decoder -----------------
|
||||||
|
public static ushort[] Decode(ReadOnlySpan<byte> src)
|
||||||
|
{
|
||||||
|
var result = new List<ushort>();
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
while (pos < src.Length)
|
||||||
|
{
|
||||||
|
byte h = src[pos++];
|
||||||
|
|
||||||
|
if ((h & 0x80) == 0)
|
||||||
|
{
|
||||||
|
// Fast path byte (0..127)
|
||||||
|
result.Add(h);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = ((h >> 3) & 0xF) + 1; // 1..16
|
||||||
|
int width = (h & 0x7) + 1; // 1..8 (expect 1..2)
|
||||||
|
|
||||||
|
if (width > 2)
|
||||||
|
throw new NotSupportedException($"Width {width} bytes exceeds uint16 capacity.");
|
||||||
|
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
uint val = (uint)ReadLE(src, ref pos, width);
|
||||||
|
if (val > 0xFFFFu)
|
||||||
|
throw new OverflowException("Decoded value exceeds UInt16 range.");
|
||||||
|
result.Add((ushort)val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Helpers -----------------
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static int WidthFromUnsigned(ushort v) => (v <= 0xFF) ? 1 : 2;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static void WriteLE(List<byte> dst, ushort value, int width)
|
||||||
|
{
|
||||||
|
// width is 1 or 2
|
||||||
|
dst.Add((byte)(value & 0xFF));
|
||||||
|
if (width == 2) dst.Add((byte)(value >> 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static ulong ReadLE(ReadOnlySpan<byte> src, ref int pos, int width)
|
||||||
|
{
|
||||||
|
if (pos + width > src.Length)
|
||||||
|
throw new ArgumentException("Buffer underflow while reading payload.");
|
||||||
|
|
||||||
|
ulong v = src[pos++]; // first byte (LSB)
|
||||||
|
if (width == 2) v |= (ulong)src[pos++] << 8;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
125
Esiur/Data/GVWIE/GroupUInt32Codec.cs
Normal file
125
Esiur/Data/GVWIE/GroupUInt32Codec.cs
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Esiur.Data.GVWIE;
|
||||||
|
|
||||||
|
public static class GroupUInt32Codec
|
||||||
|
{
|
||||||
|
// ----------------- Encoder -----------------
|
||||||
|
public static byte[] Encode(IList<uint> values)
|
||||||
|
{
|
||||||
|
if (values is null) throw new ArgumentNullException(nameof(values));
|
||||||
|
|
||||||
|
var dst = new List<byte>(values.Count * 2);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (i < values.Count)
|
||||||
|
{
|
||||||
|
uint v = values[i];
|
||||||
|
|
||||||
|
// Fast path: single byte for 0..127
|
||||||
|
if (v <= 0x7Fu)
|
||||||
|
{
|
||||||
|
dst.Add((byte)v); // MSB=0 implicitly
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group path: up to 16 items sharing a common width (1..4 bytes for uint32)
|
||||||
|
int start = i;
|
||||||
|
int count = 1;
|
||||||
|
int width = WidthFromUnsigned(v);
|
||||||
|
|
||||||
|
while (count < 16 && (i + count) < values.Count)
|
||||||
|
{
|
||||||
|
uint v2 = values[i + count];
|
||||||
|
int w2 = WidthFromUnsigned(v2);
|
||||||
|
if (w2 > width) width = w2;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header: 1 | (count-1)[4b] | (width-1)[3b]
|
||||||
|
byte header = 0x80;
|
||||||
|
header |= (byte)(((count - 1) & 0xF) << 3);
|
||||||
|
header |= (byte)((width - 1) & 0x7);
|
||||||
|
dst.Add(header);
|
||||||
|
|
||||||
|
// Payload
|
||||||
|
for (int k = 0; k < count; k++)
|
||||||
|
{
|
||||||
|
WriteLE(dst, values[start + k], width);
|
||||||
|
}
|
||||||
|
|
||||||
|
i += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Decoder -----------------
|
||||||
|
public static uint[] Decode(ReadOnlySpan<byte> src)
|
||||||
|
{
|
||||||
|
var result = new List<uint>();
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
while (pos < src.Length)
|
||||||
|
{
|
||||||
|
byte h = src[pos++];
|
||||||
|
|
||||||
|
if ((h & 0x80) == 0)
|
||||||
|
{
|
||||||
|
// Fast path byte (0..127)
|
||||||
|
result.Add(h);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = ((h >> 3) & 0xF) + 1; // 1..16
|
||||||
|
int width = (h & 0x7) + 1; // 1..8 (we expect 1..4)
|
||||||
|
|
||||||
|
if (width > 4)
|
||||||
|
throw new NotSupportedException($"Width {width} bytes exceeds uint32 capacity.");
|
||||||
|
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
uint val = (uint)ReadLE(src, ref pos, width);
|
||||||
|
result.Add(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Helpers -----------------
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static int WidthFromUnsigned(uint v)
|
||||||
|
{
|
||||||
|
if (v <= 0xFFu) return 1;
|
||||||
|
if (v <= 0xFFFFu) return 2;
|
||||||
|
if (v <= 0xFFFFFFu) return 3;
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static void WriteLE(List<byte> dst, uint value, int width)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
dst.Add((byte)((value >> (8 * i)) & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static ulong ReadLE(ReadOnlySpan<byte> src, ref int pos, int width)
|
||||||
|
{
|
||||||
|
if (pos + width > src.Length)
|
||||||
|
throw new ArgumentException("Buffer underflow while reading payload.");
|
||||||
|
|
||||||
|
ulong v = 0;
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
v |= (ulong)src[pos++] << (8 * i);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
132
Esiur/Data/GVWIE/GroupUInt64Codec.cs
Normal file
132
Esiur/Data/GVWIE/GroupUInt64Codec.cs
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Esiur.Data.GVWIE;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
public static class GroupUInt64Codec
|
||||||
|
{
|
||||||
|
// ----------------- Encoder -----------------
|
||||||
|
public static byte[] Encode(IList<ulong> values)
|
||||||
|
{
|
||||||
|
if (values is null) throw new ArgumentNullException(nameof(values));
|
||||||
|
|
||||||
|
var dst = new List<byte>(values.Count * 2);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (i < values.Count)
|
||||||
|
{
|
||||||
|
ulong v = values[i];
|
||||||
|
|
||||||
|
// Fast path: single byte for 0..127
|
||||||
|
if (v <= 0x7FUL)
|
||||||
|
{
|
||||||
|
dst.Add((byte)v); // MSB = 0 implicitly
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group path: up to 16 items sharing max width (1..8 bytes)
|
||||||
|
int start = i;
|
||||||
|
int count = 1;
|
||||||
|
int width = WidthFromUnsigned(v);
|
||||||
|
|
||||||
|
while (count < 16 && (i + count) < values.Count)
|
||||||
|
{
|
||||||
|
ulong v2 = values[i + count];
|
||||||
|
int w2 = WidthFromUnsigned(v2);
|
||||||
|
if (w2 > width) width = w2;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header: 1 | (count-1)[4b] | (width-1)[3b]
|
||||||
|
byte header = 0x80;
|
||||||
|
header |= (byte)(((count - 1) & 0xF) << 3);
|
||||||
|
header |= (byte)((width - 1) & 0x7);
|
||||||
|
dst.Add(header);
|
||||||
|
|
||||||
|
// Payload
|
||||||
|
for (int k = 0; k < count; k++)
|
||||||
|
WriteLE(dst, values[start + k], width);
|
||||||
|
|
||||||
|
i += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Decoder -----------------
|
||||||
|
public static ulong[] Decode(ReadOnlySpan<byte> src)
|
||||||
|
{
|
||||||
|
var result = new List<ulong>();
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
while (pos < src.Length)
|
||||||
|
{
|
||||||
|
byte h = src[pos++];
|
||||||
|
|
||||||
|
if ((h & 0x80) == 0)
|
||||||
|
{
|
||||||
|
// Fast path byte (0..127)
|
||||||
|
result.Add(h);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = ((h >> 3) & 0xF) + 1; // 1..16
|
||||||
|
int width = (h & 0x7) + 1; // 1..8
|
||||||
|
|
||||||
|
if (width < 1 || width > 8)
|
||||||
|
throw new NotSupportedException($"Invalid width {width} in header.");
|
||||||
|
|
||||||
|
for (int j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
ulong val = ReadLE(src, ref pos, width);
|
||||||
|
result.Add(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------- Helpers -----------------
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static int WidthFromUnsigned(ulong v)
|
||||||
|
{
|
||||||
|
if (v <= 0xFFUL) return 1;
|
||||||
|
if (v <= 0xFFFFUL) return 2;
|
||||||
|
if (v <= 0xFFFFFFUL) return 3;
|
||||||
|
if (v <= 0xFFFFFFFFUL) return 4;
|
||||||
|
if (v <= 0xFFFFFFFFFFUL) return 5;
|
||||||
|
if (v <= 0xFFFFFFFFFFFFUL) return 6;
|
||||||
|
if (v <= 0xFFFFFFFFFFFFFFUL) return 7;
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static void WriteLE(List<byte> dst, ulong value, int width)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
dst.Add((byte)((value >> (8 * i)) & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static ulong ReadLE(ReadOnlySpan<byte> src, ref int pos, int width)
|
||||||
|
{
|
||||||
|
if (pos + width > src.Length)
|
||||||
|
throw new ArgumentException("Buffer underflow while reading payload.");
|
||||||
|
|
||||||
|
ulong v = 0;
|
||||||
|
for (int i = 0; i < width; i++)
|
||||||
|
v |= (ulong)src[pos++] << (8 * i);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,536 +0,0 @@
|
|||||||
using Esiur.Core;
|
|
||||||
using Esiur.Net.IIP;
|
|
||||||
using Esiur.Resource;
|
|
||||||
using Esiur.Resource.Template;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Dynamic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
namespace Esiur.Data
|
|
||||||
{
|
|
||||||
public enum RepresentationTypeIdentifier
|
|
||||||
{
|
|
||||||
Void = 0x0,
|
|
||||||
Dynamic = 0x1,
|
|
||||||
Bool = 0x2,
|
|
||||||
UInt8,
|
|
||||||
Int8,
|
|
||||||
Char,
|
|
||||||
UInt16,
|
|
||||||
Int16,
|
|
||||||
UInt32,
|
|
||||||
Int32,
|
|
||||||
Float32,
|
|
||||||
UInt64,
|
|
||||||
Int64,
|
|
||||||
Float64,
|
|
||||||
DateTime,
|
|
||||||
UInt128,
|
|
||||||
Int128,
|
|
||||||
Decimal,
|
|
||||||
String,
|
|
||||||
RawData,
|
|
||||||
Resource,
|
|
||||||
Record,
|
|
||||||
List,
|
|
||||||
Map,
|
|
||||||
Enum = 0x44,
|
|
||||||
TypedResource = 0x45, // Followed by UUID
|
|
||||||
TypedRecord = 0x46, // Followed by UUID
|
|
||||||
TypedList = 0x48, // Followed by element type
|
|
||||||
Tuple2 = 0x50, // Followed by element type
|
|
||||||
TypedMap = 0x51, // Followed by key type and value type
|
|
||||||
Tuple3 = 0x58,
|
|
||||||
Tuple4 = 0x60,
|
|
||||||
Tuple5 = 0x68,
|
|
||||||
Tuple6 = 0x70,
|
|
||||||
Tuple7 = 0x78
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RepresentationType
|
|
||||||
{
|
|
||||||
|
|
||||||
static RepresentationTypeIdentifier[] refTypes = new RepresentationTypeIdentifier[]
|
|
||||||
{
|
|
||||||
RepresentationTypeIdentifier.Dynamic,
|
|
||||||
RepresentationTypeIdentifier.RawData,
|
|
||||||
RepresentationTypeIdentifier.String,
|
|
||||||
RepresentationTypeIdentifier.Resource,
|
|
||||||
RepresentationTypeIdentifier.Record,
|
|
||||||
RepresentationTypeIdentifier.Map,
|
|
||||||
RepresentationTypeIdentifier.List,
|
|
||||||
RepresentationTypeIdentifier.TypedList,
|
|
||||||
RepresentationTypeIdentifier.TypedMap,
|
|
||||||
RepresentationTypeIdentifier.Tuple2,
|
|
||||||
RepresentationTypeIdentifier.Tuple3,
|
|
||||||
RepresentationTypeIdentifier.Tuple4,
|
|
||||||
RepresentationTypeIdentifier.Tuple5,
|
|
||||||
RepresentationTypeIdentifier.Tuple6,
|
|
||||||
RepresentationTypeIdentifier.Tuple7,
|
|
||||||
RepresentationTypeIdentifier.TypedRecord,
|
|
||||||
RepresentationTypeIdentifier.TypedResource
|
|
||||||
};
|
|
||||||
|
|
||||||
static Map<TDUIdentifier, RepresentationTypeIdentifier> typesMap = new Map<TDUIdentifier, RepresentationTypeIdentifier>()
|
|
||||||
{
|
|
||||||
[TDUIdentifier.UInt8] = RepresentationTypeIdentifier.UInt8,
|
|
||||||
[TDUIdentifier.Int8] = RepresentationTypeIdentifier.Int8,
|
|
||||||
[TDUIdentifier.UInt16] = RepresentationTypeIdentifier.UInt16,
|
|
||||||
[TDUIdentifier.Int16] = RepresentationTypeIdentifier.Int16,
|
|
||||||
[TDUIdentifier.UInt32] = RepresentationTypeIdentifier.UInt32,
|
|
||||||
[TDUIdentifier.Int32] = RepresentationTypeIdentifier.Int32,
|
|
||||||
[TDUIdentifier.UInt64] = RepresentationTypeIdentifier.UInt64,
|
|
||||||
[TDUIdentifier.Int64] = RepresentationTypeIdentifier.Int64,
|
|
||||||
[TDUIdentifier.UInt128] = RepresentationTypeIdentifier.UInt128,
|
|
||||||
[TDUIdentifier.Int128] = RepresentationTypeIdentifier.Int128,
|
|
||||||
[TDUIdentifier.Char8] = RepresentationTypeIdentifier.Char,
|
|
||||||
[TDUIdentifier.DateTime] = RepresentationTypeIdentifier.DateTime,
|
|
||||||
[TDUIdentifier.Float32] = RepresentationTypeIdentifier.Float32,
|
|
||||||
[TDUIdentifier.Float64] = RepresentationTypeIdentifier.Float64,
|
|
||||||
[TDUIdentifier.Decimal128] = RepresentationTypeIdentifier.Decimal,
|
|
||||||
[TDUIdentifier.False] = RepresentationTypeIdentifier.Bool,
|
|
||||||
[TDUIdentifier.True] = RepresentationTypeIdentifier.Bool,
|
|
||||||
[TDUIdentifier.Map] = RepresentationTypeIdentifier.Map,
|
|
||||||
[TDUIdentifier.List] = RepresentationTypeIdentifier.List,
|
|
||||||
[TDUIdentifier.RawData] = RepresentationTypeIdentifier.RawData,
|
|
||||||
[TDUIdentifier.Record] = RepresentationTypeIdentifier.Record,
|
|
||||||
[TDUIdentifier.String] = RepresentationTypeIdentifier.String,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void SetNull(List<byte> flags)
|
|
||||||
{
|
|
||||||
if (refTypes.Contains(Identifier))
|
|
||||||
{
|
|
||||||
Nullable = (flags.FirstOrDefault() == 2);
|
|
||||||
if (flags.Count > 0)
|
|
||||||
flags.RemoveAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SubTypes != null)
|
|
||||||
foreach (var st in SubTypes)
|
|
||||||
st.SetNull(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetNull(byte flag)
|
|
||||||
{
|
|
||||||
if (refTypes.Contains(Identifier))
|
|
||||||
{
|
|
||||||
Nullable = (flag == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SubTypes != null)
|
|
||||||
foreach (var st in SubTypes)
|
|
||||||
st.SetNull(flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void SetNotNull(List<byte> flags)
|
|
||||||
{
|
|
||||||
if (refTypes.Contains(Identifier))
|
|
||||||
{
|
|
||||||
Nullable = (flags.FirstOrDefault() != 1);
|
|
||||||
if (flags.Count > 0)
|
|
||||||
flags.RemoveAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SubTypes != null)
|
|
||||||
foreach (var st in SubTypes)
|
|
||||||
st.SetNotNull(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (SubTypes != null && SubTypes.Length > 0)
|
|
||||||
return Identifier.ToString() + "<" + String.Join(",", SubTypes.Select(x => x.ToString())) + ">" + (Nullable ? "?" : "");
|
|
||||||
return Identifier.ToString() + (Nullable ? "?" : "");
|
|
||||||
}
|
|
||||||
public void SetNotNull(byte flag)
|
|
||||||
{
|
|
||||||
if (refTypes.Contains(Identifier))
|
|
||||||
{
|
|
||||||
Nullable = (flag != 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SubTypes != null)
|
|
||||||
foreach (var st in SubTypes)
|
|
||||||
st.SetNotNull(flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type? GetRuntimeType(Warehouse warehouse)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (Identifier == RepresentationTypeIdentifier.TypedList)
|
|
||||||
{
|
|
||||||
var sub = SubTypes?[0].GetRuntimeType(warehouse);
|
|
||||||
if (sub == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var rt = sub.MakeArrayType();
|
|
||||||
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
else if (Identifier == RepresentationTypeIdentifier.TypedMap)
|
|
||||||
{
|
|
||||||
var subs = SubTypes.Select(x => x.GetRuntimeType(warehouse)).ToArray();
|
|
||||||
var rt = typeof(Map<,>).MakeGenericType(subs);
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Identifier switch
|
|
||||||
{
|
|
||||||
(RepresentationTypeIdentifier.Void) => typeof(void),
|
|
||||||
(RepresentationTypeIdentifier.Dynamic) => typeof(object),
|
|
||||||
(RepresentationTypeIdentifier.Bool) => Nullable ? typeof(bool?) : typeof(bool),
|
|
||||||
(RepresentationTypeIdentifier.Char) => Nullable ? typeof(char?) : typeof(char),
|
|
||||||
(RepresentationTypeIdentifier.UInt8) => Nullable ? typeof(byte?) : typeof(byte),
|
|
||||||
(RepresentationTypeIdentifier.Int8) => Nullable ? typeof(sbyte?) : typeof(sbyte),
|
|
||||||
(RepresentationTypeIdentifier.Int16) => Nullable ? typeof(short?) : typeof(short),
|
|
||||||
(RepresentationTypeIdentifier.UInt16) => Nullable ? typeof(ushort?) : typeof(ushort),
|
|
||||||
(RepresentationTypeIdentifier.Int32) => Nullable ? typeof(int?) : typeof(int),
|
|
||||||
(RepresentationTypeIdentifier.UInt32) => Nullable ? typeof(uint?) : typeof(uint),
|
|
||||||
(RepresentationTypeIdentifier.Int64) => Nullable ? typeof(ulong?) : typeof(long),
|
|
||||||
(RepresentationTypeIdentifier.UInt64) => Nullable ? typeof(ulong?) : typeof(ulong),
|
|
||||||
(RepresentationTypeIdentifier.Float32) => Nullable ? typeof(float?) : typeof(float),
|
|
||||||
(RepresentationTypeIdentifier.Float64) => Nullable ? typeof(double?) : typeof(double),
|
|
||||||
(RepresentationTypeIdentifier.Decimal) => Nullable ? typeof(decimal?) : typeof(decimal),
|
|
||||||
(RepresentationTypeIdentifier.String) => typeof(string),
|
|
||||||
(RepresentationTypeIdentifier.DateTime) => Nullable ? typeof(DateTime?) : typeof(DateTime),
|
|
||||||
(RepresentationTypeIdentifier.Resource) => typeof(IResource),
|
|
||||||
(RepresentationTypeIdentifier.Record) => typeof(IRecord),
|
|
||||||
(RepresentationTypeIdentifier.TypedRecord) => warehouse.GetTemplateByClassId((UUID)UUID!, TemplateType.Record)?.DefinedType,
|
|
||||||
(RepresentationTypeIdentifier.TypedResource) => warehouse.GetTemplateByClassId((UUID)UUID!, TemplateType.Resource)?.DefinedType,
|
|
||||||
(RepresentationTypeIdentifier.Enum) =>warehouse.GetTemplateByClassId((UUID)UUID!, TemplateType.Enum)?.DefinedType,
|
|
||||||
|
|
||||||
_ => null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public RepresentationTypeIdentifier Identifier;
|
|
||||||
public bool Nullable;
|
|
||||||
public UUID? UUID;
|
|
||||||
//public RepresentationType? SubType1; // List + Map
|
|
||||||
//public RepresentationType? SubType2; // Map
|
|
||||||
//public RepresentationType? SubType3; // No types yet
|
|
||||||
|
|
||||||
public RepresentationType[]? SubTypes = null;
|
|
||||||
|
|
||||||
public RepresentationType ToNullable()
|
|
||||||
{
|
|
||||||
return new RepresentationType(Identifier, true, UUID, SubTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RepresentationType? FromType(Type type)
|
|
||||||
{
|
|
||||||
|
|
||||||
var nullable = false;
|
|
||||||
|
|
||||||
var nullType = System.Nullable.GetUnderlyingType(type);
|
|
||||||
|
|
||||||
if (nullType != null)
|
|
||||||
{
|
|
||||||
type = nullType;
|
|
||||||
nullable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == typeof(IResource))
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.Resource, nullable);
|
|
||||||
else if (type == typeof(IRecord) || type == typeof(Record))
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.Record, nullable);
|
|
||||||
else if (type == typeof(Map<object, object>)
|
|
||||||
|| type == typeof(Dictionary<object, object>))
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.Map, nullable);
|
|
||||||
else if (Codec.ImplementsInterface(type, typeof(IResource)))
|
|
||||||
{
|
|
||||||
return new RepresentationType(
|
|
||||||
RepresentationTypeIdentifier.TypedResource,
|
|
||||||
nullable,
|
|
||||||
TypeTemplate.GetTypeUUID(type)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
|
|
||||||
{
|
|
||||||
return new RepresentationType(
|
|
||||||
RepresentationTypeIdentifier.TypedRecord,
|
|
||||||
nullable,
|
|
||||||
TypeTemplate.GetTypeUUID(type)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (type.IsGenericType)
|
|
||||||
{
|
|
||||||
var genericType = type.GetGenericTypeDefinition();
|
|
||||||
if (genericType == typeof(List<>)
|
|
||||||
|| genericType == typeof(VarList<>)
|
|
||||||
|| genericType == typeof(IList<>))
|
|
||||||
{
|
|
||||||
var args = type.GetGenericArguments();
|
|
||||||
if (args[0] == typeof(object))
|
|
||||||
{
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.List, nullable);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var subType = FromType(args[0]);
|
|
||||||
if (subType == null) // unrecongnized type
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.TypedList, nullable, null,
|
|
||||||
new RepresentationType[] { subType });
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (genericType == typeof(Map<,>)
|
|
||||||
|| genericType == typeof(Dictionary<,>))
|
|
||||||
{
|
|
||||||
var args = type.GetGenericArguments();
|
|
||||||
if (args[0] == typeof(object) && args[1] == typeof(object))
|
|
||||||
{
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.Map, nullable);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var subType1 = FromType(args[0]);
|
|
||||||
if (subType1 == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var subType2 = FromType(args[1]);
|
|
||||||
if (subType2 == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.TypedMap, nullable, null,
|
|
||||||
new RepresentationType[] { subType1, subType2 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//else if (genericType == typeof(AsyncReply<>))
|
|
||||||
//{
|
|
||||||
// var args = type.GetGenericArguments();
|
|
||||||
// return FromType(args[0]);
|
|
||||||
//}
|
|
||||||
//else if (genericType == typeof(DistributedPropertyContext<>))
|
|
||||||
//{
|
|
||||||
// var args = type.GetGenericArguments();
|
|
||||||
// return FromType(args[0]);
|
|
||||||
//}
|
|
||||||
else if (genericType == typeof(ValueTuple<,>))
|
|
||||||
{
|
|
||||||
var args = type.GetGenericArguments();
|
|
||||||
var subTypes = new RepresentationType[args.Length];
|
|
||||||
for (var i = 0; i < args.Length; i++)
|
|
||||||
{
|
|
||||||
var t = FromType(args[i]);
|
|
||||||
if (t == null)
|
|
||||||
return null;
|
|
||||||
subTypes[i] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple2, nullable, null, subTypes);
|
|
||||||
}
|
|
||||||
else if (genericType == typeof(ValueTuple<,,>))
|
|
||||||
{
|
|
||||||
var args = type.GetGenericArguments();
|
|
||||||
var subTypes = new RepresentationType[args.Length];
|
|
||||||
for (var i = 0; i < args.Length; i++)
|
|
||||||
{
|
|
||||||
var t = FromType(args[i]);
|
|
||||||
if (t == null)
|
|
||||||
return null;
|
|
||||||
subTypes[i] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple3, nullable, null, subTypes);
|
|
||||||
}
|
|
||||||
else if (genericType == typeof(ValueTuple<,,,>))
|
|
||||||
{
|
|
||||||
|
|
||||||
var args = type.GetGenericArguments();
|
|
||||||
var subTypes = new RepresentationType[args.Length];
|
|
||||||
for (var i = 0; i < args.Length; i++)
|
|
||||||
{
|
|
||||||
var t = FromType(args[i]);
|
|
||||||
if (t == null)
|
|
||||||
return null;
|
|
||||||
subTypes[i] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple4, nullable, null, subTypes);
|
|
||||||
}
|
|
||||||
else if (genericType == typeof(ValueTuple<,,,,>))
|
|
||||||
{
|
|
||||||
var args = type.GetGenericArguments();
|
|
||||||
var subTypes = new RepresentationType[args.Length];
|
|
||||||
for (var i = 0; i < args.Length; i++)
|
|
||||||
{
|
|
||||||
var t = FromType(args[i]);
|
|
||||||
if (t == null)
|
|
||||||
return null;
|
|
||||||
subTypes[i] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple5, nullable, null, subTypes);
|
|
||||||
}
|
|
||||||
else if (genericType == typeof(ValueTuple<,,,,,>))
|
|
||||||
{
|
|
||||||
var args = type.GetGenericArguments();
|
|
||||||
var subTypes = new RepresentationType[args.Length];
|
|
||||||
for (var i = 0; i < args.Length; i++)
|
|
||||||
{
|
|
||||||
var t = FromType(args[i]);
|
|
||||||
if (t == null)
|
|
||||||
return null;
|
|
||||||
subTypes[i] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple6, nullable, null, subTypes);
|
|
||||||
}
|
|
||||||
else if (genericType == typeof(ValueTuple<,,,,,,>))
|
|
||||||
{
|
|
||||||
var args = type.GetGenericArguments();
|
|
||||||
var subTypes = new RepresentationType[args.Length];
|
|
||||||
for (var i = 0; i < args.Length; i++)
|
|
||||||
{
|
|
||||||
var t = FromType(args[i]);
|
|
||||||
if (t == null)
|
|
||||||
return null;
|
|
||||||
subTypes[i] = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple7, nullable, null, subTypes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else if (type.IsArray)
|
|
||||||
{
|
|
||||||
var elementType = type.GetElementType();
|
|
||||||
if (elementType == typeof(object))
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.List, nullable);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var subType = FromType(elementType);
|
|
||||||
|
|
||||||
if (subType == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.TypedList, nullable, null,
|
|
||||||
new RepresentationType[] { subType });
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (type.IsEnum)
|
|
||||||
{
|
|
||||||
return new RepresentationType(RepresentationTypeIdentifier.Enum, nullable, TypeTemplate.GetTypeUUID(type));
|
|
||||||
}
|
|
||||||
else if (type.IsInterface)
|
|
||||||
{
|
|
||||||
return null; // other interfaces are not supported
|
|
||||||
}
|
|
||||||
|
|
||||||
//else if (typeof(Structure).IsAssignableFrom(t) || t == typeof(ExpandoObject) => RepresentationTypeIdentifier.Structure)
|
|
||||||
//{
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
return type switch
|
|
||||||
{
|
|
||||||
_ when type == typeof(void) => new RepresentationType(RepresentationTypeIdentifier.Void, nullable),
|
|
||||||
_ when type == typeof(object) => new RepresentationType(RepresentationTypeIdentifier.Dynamic, nullable),
|
|
||||||
_ when type == typeof(bool) => new RepresentationType(RepresentationTypeIdentifier.Bool, nullable),
|
|
||||||
_ when type == typeof(char) => new RepresentationType(RepresentationTypeIdentifier.Char, nullable),
|
|
||||||
_ when type == typeof(byte) => new RepresentationType(RepresentationTypeIdentifier.UInt8, nullable),
|
|
||||||
_ when type == typeof(sbyte) => new RepresentationType(RepresentationTypeIdentifier.Int8, nullable),
|
|
||||||
_ when type == typeof(short) => new RepresentationType(RepresentationTypeIdentifier.Int16, nullable),
|
|
||||||
_ when type == typeof(ushort) => new RepresentationType(RepresentationTypeIdentifier.UInt16, nullable),
|
|
||||||
_ when type == typeof(int) => new RepresentationType(RepresentationTypeIdentifier.Int32, nullable),
|
|
||||||
_ when type == typeof(uint) => new RepresentationType(RepresentationTypeIdentifier.UInt32, nullable),
|
|
||||||
_ when type == typeof(long) => new RepresentationType(RepresentationTypeIdentifier.Int64, nullable),
|
|
||||||
_ when type == typeof(ulong) => new RepresentationType(RepresentationTypeIdentifier.UInt64, nullable),
|
|
||||||
_ when type == typeof(float) => new RepresentationType(RepresentationTypeIdentifier.Float32, nullable),
|
|
||||||
_ when type == typeof(double) => new RepresentationType(RepresentationTypeIdentifier.Float64, nullable),
|
|
||||||
_ when type == typeof(decimal) => new RepresentationType(RepresentationTypeIdentifier.Decimal, nullable),
|
|
||||||
_ when type == typeof(string) => new RepresentationType(RepresentationTypeIdentifier.String, nullable),
|
|
||||||
_ when type == typeof(DateTime) => new RepresentationType(RepresentationTypeIdentifier.DateTime, nullable),
|
|
||||||
_ => null
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public RepresentationType(RepresentationTypeIdentifier identifier, bool nullable, UUID? uuid = null, RepresentationType[]? subTypes = null)
|
|
||||||
{
|
|
||||||
Nullable = nullable;
|
|
||||||
Identifier = identifier;
|
|
||||||
UUID = uuid;
|
|
||||||
SubTypes = subTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Compose()
|
|
||||||
{
|
|
||||||
var rt = new BinaryList();
|
|
||||||
|
|
||||||
if (Nullable)
|
|
||||||
rt.AddUInt8((byte)(0x80 | (byte)Identifier));
|
|
||||||
else
|
|
||||||
rt.AddUInt8((byte)Identifier);
|
|
||||||
|
|
||||||
if (UUID != null)
|
|
||||||
rt.AddUInt8Array(UUID.Value.Data);
|
|
||||||
|
|
||||||
if (SubTypes != null)
|
|
||||||
for (var i = 0; i < SubTypes.Length; i++)
|
|
||||||
rt.AddUInt8Array(SubTypes[i].Compose());
|
|
||||||
|
|
||||||
return rt.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//public override string ToString() => Identifier.ToString() + (Nullable ? "?" : "")
|
|
||||||
// + TypeTemplate != null ? "<" + TypeTemplate.ClassName + ">" : "";
|
|
||||||
|
|
||||||
|
|
||||||
public static (uint, RepresentationType) Parse(byte[] data, uint offset)
|
|
||||||
{
|
|
||||||
var oOffset = offset;
|
|
||||||
|
|
||||||
var header = data[offset++];
|
|
||||||
bool nullable = (header & 0x80) > 0;
|
|
||||||
var identifier = (RepresentationTypeIdentifier)(header & 0x7F);
|
|
||||||
|
|
||||||
|
|
||||||
if ((header & 0x40) > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
var hasUUID = (header & 0x4) > 0;
|
|
||||||
var subsCount = (header >> 3) & 0x7;
|
|
||||||
|
|
||||||
UUID? uuid = null;
|
|
||||||
|
|
||||||
if (hasUUID)
|
|
||||||
{
|
|
||||||
uuid = data.GetUUID(offset);
|
|
||||||
offset += 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
var subs = new RepresentationType[subsCount];
|
|
||||||
|
|
||||||
for (var i = 0; i < subsCount; i++)
|
|
||||||
{
|
|
||||||
(var len, subs[i]) = RepresentationType.Parse(data, offset);
|
|
||||||
offset += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (offset - oOffset, new RepresentationType(identifier, nullable, uuid, subs));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (1, new RepresentationType(identifier, nullable));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -61,6 +61,7 @@ public struct TDU
|
|||||||
public TDU(TDUIdentifier identifier)
|
public TDU(TDUIdentifier identifier)
|
||||||
{
|
{
|
||||||
Identifier = identifier;
|
Identifier = identifier;
|
||||||
|
Composed = new byte[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public TDU(TDUIdentifier identifier,
|
public TDU(TDUIdentifier identifier,
|
||||||
@@ -74,7 +75,10 @@ public struct TDU
|
|||||||
|
|
||||||
if (Class == TDUClass.Fixed)
|
if (Class == TDUClass.Fixed)
|
||||||
{
|
{
|
||||||
Composed = DC.Combine(new byte[] { (byte)Identifier }, 0, 1, data, 0, (uint)length);
|
if (length == 0)
|
||||||
|
Composed = new byte[1] { (byte)identifier };
|
||||||
|
else
|
||||||
|
Composed = DC.Combine(new byte[] { (byte)Identifier }, 0, 1, data, 0, (uint)length);
|
||||||
}
|
}
|
||||||
else if (Class == TDUClass.Dynamic
|
else if (Class == TDUClass.Dynamic
|
||||||
|| Class == TDUClass.Extension)
|
|| Class == TDUClass.Extension)
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ namespace Esiur.Data
|
|||||||
TypedConstant = 0x85,
|
TypedConstant = 0x85,
|
||||||
|
|
||||||
TypeContinuation = 0xC0,
|
TypeContinuation = 0xC0,
|
||||||
|
TypeOfTarget = 0xC1,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
502
Esiur/Data/TRU.cs
Normal file
502
Esiur/Data/TRU.cs
Normal file
@@ -0,0 +1,502 @@
|
|||||||
|
using Esiur.Core;
|
||||||
|
using Esiur.Net.IIP;
|
||||||
|
using Esiur.Resource;
|
||||||
|
using Esiur.Resource.Template;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace Esiur.Data
|
||||||
|
{
|
||||||
|
public class TRU
|
||||||
|
{
|
||||||
|
|
||||||
|
static TRUIdentifier[] refTypes = new TRUIdentifier[]
|
||||||
|
{
|
||||||
|
TRUIdentifier.Dynamic,
|
||||||
|
TRUIdentifier.RawData,
|
||||||
|
TRUIdentifier.String,
|
||||||
|
TRUIdentifier.Resource,
|
||||||
|
TRUIdentifier.Record,
|
||||||
|
TRUIdentifier.Map,
|
||||||
|
TRUIdentifier.List,
|
||||||
|
TRUIdentifier.TypedList,
|
||||||
|
TRUIdentifier.TypedMap,
|
||||||
|
TRUIdentifier.Tuple2,
|
||||||
|
TRUIdentifier.Tuple3,
|
||||||
|
TRUIdentifier.Tuple4,
|
||||||
|
TRUIdentifier.Tuple5,
|
||||||
|
TRUIdentifier.Tuple6,
|
||||||
|
TRUIdentifier.Tuple7,
|
||||||
|
TRUIdentifier.TypedRecord,
|
||||||
|
TRUIdentifier.TypedResource
|
||||||
|
};
|
||||||
|
|
||||||
|
static Map<TDUIdentifier, TRUIdentifier> typesMap = new Map<TDUIdentifier, TRUIdentifier>()
|
||||||
|
{
|
||||||
|
[TDUIdentifier.UInt8] = TRUIdentifier.UInt8,
|
||||||
|
[TDUIdentifier.Int8] = TRUIdentifier.Int8,
|
||||||
|
[TDUIdentifier.UInt16] = TRUIdentifier.UInt16,
|
||||||
|
[TDUIdentifier.Int16] = TRUIdentifier.Int16,
|
||||||
|
[TDUIdentifier.UInt32] = TRUIdentifier.UInt32,
|
||||||
|
[TDUIdentifier.Int32] = TRUIdentifier.Int32,
|
||||||
|
[TDUIdentifier.UInt64] = TRUIdentifier.UInt64,
|
||||||
|
[TDUIdentifier.Int64] = TRUIdentifier.Int64,
|
||||||
|
[TDUIdentifier.UInt128] = TRUIdentifier.UInt128,
|
||||||
|
[TDUIdentifier.Int128] = TRUIdentifier.Int128,
|
||||||
|
[TDUIdentifier.Char8] = TRUIdentifier.Char,
|
||||||
|
[TDUIdentifier.DateTime] = TRUIdentifier.DateTime,
|
||||||
|
[TDUIdentifier.Float32] = TRUIdentifier.Float32,
|
||||||
|
[TDUIdentifier.Float64] = TRUIdentifier.Float64,
|
||||||
|
[TDUIdentifier.Decimal128] = TRUIdentifier.Decimal,
|
||||||
|
[TDUIdentifier.False] = TRUIdentifier.Bool,
|
||||||
|
[TDUIdentifier.True] = TRUIdentifier.Bool,
|
||||||
|
[TDUIdentifier.Map] = TRUIdentifier.Map,
|
||||||
|
[TDUIdentifier.List] = TRUIdentifier.List,
|
||||||
|
[TDUIdentifier.RawData] = TRUIdentifier.RawData,
|
||||||
|
[TDUIdentifier.Record] = TRUIdentifier.Record,
|
||||||
|
[TDUIdentifier.String] = TRUIdentifier.String,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void SetNull(List<byte> flags)
|
||||||
|
{
|
||||||
|
if (refTypes.Contains(Identifier))
|
||||||
|
{
|
||||||
|
Nullable = (flags.FirstOrDefault() == 2);
|
||||||
|
if (flags.Count > 0)
|
||||||
|
flags.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SubTypes != null)
|
||||||
|
foreach (var st in SubTypes)
|
||||||
|
st.SetNull(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetNull(byte flag)
|
||||||
|
{
|
||||||
|
if (refTypes.Contains(Identifier))
|
||||||
|
{
|
||||||
|
Nullable = (flag == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SubTypes != null)
|
||||||
|
foreach (var st in SubTypes)
|
||||||
|
st.SetNull(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void SetNotNull(List<byte> flags)
|
||||||
|
{
|
||||||
|
if (refTypes.Contains(Identifier))
|
||||||
|
{
|
||||||
|
Nullable = (flags.FirstOrDefault() != 1);
|
||||||
|
if (flags.Count > 0)
|
||||||
|
flags.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SubTypes != null)
|
||||||
|
foreach (var st in SubTypes)
|
||||||
|
st.SetNotNull(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (SubTypes != null && SubTypes.Length > 0)
|
||||||
|
return Identifier.ToString() + "<" + String.Join(",", SubTypes.Select(x => x.ToString())) + ">" + (Nullable ? "?" : "");
|
||||||
|
return Identifier.ToString() + (Nullable ? "?" : "");
|
||||||
|
}
|
||||||
|
public void SetNotNull(byte flag)
|
||||||
|
{
|
||||||
|
if (refTypes.Contains(Identifier))
|
||||||
|
{
|
||||||
|
Nullable = (flag != 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SubTypes != null)
|
||||||
|
foreach (var st in SubTypes)
|
||||||
|
st.SetNotNull(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type? GetRuntimeType(Warehouse warehouse)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (Identifier == TRUIdentifier.TypedList)
|
||||||
|
{
|
||||||
|
var sub = SubTypes?[0].GetRuntimeType(warehouse);
|
||||||
|
if (sub == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var rt = sub.MakeArrayType();
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
else if (Identifier == TRUIdentifier.TypedMap)
|
||||||
|
{
|
||||||
|
var subs = SubTypes.Select(x => x.GetRuntimeType(warehouse)).ToArray();
|
||||||
|
var rt = typeof(Map<,>).MakeGenericType(subs);
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Identifier switch
|
||||||
|
{
|
||||||
|
(TRUIdentifier.Void) => typeof(void),
|
||||||
|
(TRUIdentifier.Dynamic) => typeof(object),
|
||||||
|
(TRUIdentifier.Bool) => Nullable ? typeof(bool?) : typeof(bool),
|
||||||
|
(TRUIdentifier.Char) => Nullable ? typeof(char?) : typeof(char),
|
||||||
|
(TRUIdentifier.UInt8) => Nullable ? typeof(byte?) : typeof(byte),
|
||||||
|
(TRUIdentifier.Int8) => Nullable ? typeof(sbyte?) : typeof(sbyte),
|
||||||
|
(TRUIdentifier.Int16) => Nullable ? typeof(short?) : typeof(short),
|
||||||
|
(TRUIdentifier.UInt16) => Nullable ? typeof(ushort?) : typeof(ushort),
|
||||||
|
(TRUIdentifier.Int32) => Nullable ? typeof(int?) : typeof(int),
|
||||||
|
(TRUIdentifier.UInt32) => Nullable ? typeof(uint?) : typeof(uint),
|
||||||
|
(TRUIdentifier.Int64) => Nullable ? typeof(ulong?) : typeof(long),
|
||||||
|
(TRUIdentifier.UInt64) => Nullable ? typeof(ulong?) : typeof(ulong),
|
||||||
|
(TRUIdentifier.Float32) => Nullable ? typeof(float?) : typeof(float),
|
||||||
|
(TRUIdentifier.Float64) => Nullable ? typeof(double?) : typeof(double),
|
||||||
|
(TRUIdentifier.Decimal) => Nullable ? typeof(decimal?) : typeof(decimal),
|
||||||
|
(TRUIdentifier.String) => typeof(string),
|
||||||
|
(TRUIdentifier.DateTime) => Nullable ? typeof(DateTime?) : typeof(DateTime),
|
||||||
|
(TRUIdentifier.Resource) => typeof(IResource),
|
||||||
|
(TRUIdentifier.Record) => typeof(IRecord),
|
||||||
|
(TRUIdentifier.TypedRecord) => warehouse.GetTemplateByClassId((UUID)UUID!, TemplateType.Record)?.DefinedType,
|
||||||
|
(TRUIdentifier.TypedResource) => warehouse.GetTemplateByClassId((UUID)UUID!, TemplateType.Resource)?.DefinedType,
|
||||||
|
(TRUIdentifier.Enum) =>warehouse.GetTemplateByClassId((UUID)UUID!, TemplateType.Enum)?.DefinedType,
|
||||||
|
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public TRUIdentifier Identifier;
|
||||||
|
public bool Nullable;
|
||||||
|
public UUID? UUID;
|
||||||
|
//public RepresentationType? SubType1; // List + Map
|
||||||
|
//public RepresentationType? SubType2; // Map
|
||||||
|
//public RepresentationType? SubType3; // No types yet
|
||||||
|
|
||||||
|
public TRU[]? SubTypes = null;
|
||||||
|
|
||||||
|
public TRU ToNullable()
|
||||||
|
{
|
||||||
|
return new TRU(Identifier, true, UUID, SubTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Match(TRU other)
|
||||||
|
{
|
||||||
|
if (other.Identifier != Identifier)
|
||||||
|
return false;
|
||||||
|
if (other.UUID != UUID)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (other.SubTypes != null)
|
||||||
|
{
|
||||||
|
if (other.SubTypes.Length != (SubTypes?.Length ?? -1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (var i = 0; i < SubTypes?.Length; i++)
|
||||||
|
if (!SubTypes[i].Match(other.SubTypes[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TRU? FromType(Type type)
|
||||||
|
{
|
||||||
|
|
||||||
|
var nullable = false;
|
||||||
|
|
||||||
|
var nullType = System.Nullable.GetUnderlyingType(type);
|
||||||
|
|
||||||
|
if (nullType != null)
|
||||||
|
{
|
||||||
|
type = nullType;
|
||||||
|
nullable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == typeof(IResource))
|
||||||
|
return new TRU(TRUIdentifier.Resource, nullable);
|
||||||
|
else if (type == typeof(IRecord) || type == typeof(Record))
|
||||||
|
return new TRU(TRUIdentifier.Record, nullable);
|
||||||
|
else if (type == typeof(Map<object, object>)
|
||||||
|
|| type == typeof(Dictionary<object, object>))
|
||||||
|
return new TRU(TRUIdentifier.Map, nullable);
|
||||||
|
else if (Codec.ImplementsInterface(type, typeof(IResource)))
|
||||||
|
{
|
||||||
|
return new TRU(
|
||||||
|
TRUIdentifier.TypedResource,
|
||||||
|
nullable,
|
||||||
|
TypeTemplate.GetTypeUUID(type)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
|
||||||
|
{
|
||||||
|
return new TRU(
|
||||||
|
TRUIdentifier.TypedRecord,
|
||||||
|
nullable,
|
||||||
|
TypeTemplate.GetTypeUUID(type)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (type.IsGenericType)
|
||||||
|
{
|
||||||
|
var genericType = type.GetGenericTypeDefinition();
|
||||||
|
if (genericType == typeof(List<>)
|
||||||
|
|| genericType == typeof(VarList<>)
|
||||||
|
|| genericType == typeof(IList<>))
|
||||||
|
{
|
||||||
|
var args = type.GetGenericArguments();
|
||||||
|
if (args[0] == typeof(object))
|
||||||
|
{
|
||||||
|
return new TRU(TRUIdentifier.List, nullable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var subType = FromType(args[0]);
|
||||||
|
if (subType == null) // unrecongnized type
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new TRU(TRUIdentifier.TypedList, nullable, null,
|
||||||
|
new TRU[] { subType });
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (genericType == typeof(Map<,>)
|
||||||
|
|| genericType == typeof(Dictionary<,>))
|
||||||
|
{
|
||||||
|
var args = type.GetGenericArguments();
|
||||||
|
if (args[0] == typeof(object) && args[1] == typeof(object))
|
||||||
|
{
|
||||||
|
return new TRU(TRUIdentifier.Map, nullable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var subType1 = FromType(args[0]);
|
||||||
|
if (subType1 == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var subType2 = FromType(args[1]);
|
||||||
|
if (subType2 == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new TRU(TRUIdentifier.TypedMap, nullable, null,
|
||||||
|
new TRU[] { subType1, subType2 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (genericType == typeof(ValueTuple<,>))
|
||||||
|
{
|
||||||
|
var args = type.GetGenericArguments();
|
||||||
|
var subTypes = new TRU[args.Length];
|
||||||
|
for (var i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
var t = FromType(args[i]);
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
subTypes[i] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TRU(TRUIdentifier.Tuple2, nullable, null, subTypes);
|
||||||
|
}
|
||||||
|
else if (genericType == typeof(ValueTuple<,,>))
|
||||||
|
{
|
||||||
|
var args = type.GetGenericArguments();
|
||||||
|
var subTypes = new TRU[args.Length];
|
||||||
|
for (var i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
var t = FromType(args[i]);
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
subTypes[i] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TRU(TRUIdentifier.Tuple3, nullable, null, subTypes);
|
||||||
|
}
|
||||||
|
else if (genericType == typeof(ValueTuple<,,,>))
|
||||||
|
{
|
||||||
|
|
||||||
|
var args = type.GetGenericArguments();
|
||||||
|
var subTypes = new TRU[args.Length];
|
||||||
|
for (var i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
var t = FromType(args[i]);
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
subTypes[i] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TRU(TRUIdentifier.Tuple4, nullable, null, subTypes);
|
||||||
|
}
|
||||||
|
else if (genericType == typeof(ValueTuple<,,,,>))
|
||||||
|
{
|
||||||
|
var args = type.GetGenericArguments();
|
||||||
|
var subTypes = new TRU[args.Length];
|
||||||
|
for (var i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
var t = FromType(args[i]);
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
subTypes[i] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TRU(TRUIdentifier.Tuple5, nullable, null, subTypes);
|
||||||
|
}
|
||||||
|
else if (genericType == typeof(ValueTuple<,,,,,>))
|
||||||
|
{
|
||||||
|
var args = type.GetGenericArguments();
|
||||||
|
var subTypes = new TRU[args.Length];
|
||||||
|
for (var i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
var t = FromType(args[i]);
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
subTypes[i] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TRU(TRUIdentifier.Tuple6, nullable, null, subTypes);
|
||||||
|
}
|
||||||
|
else if (genericType == typeof(ValueTuple<,,,,,,>))
|
||||||
|
{
|
||||||
|
var args = type.GetGenericArguments();
|
||||||
|
var subTypes = new TRU[args.Length];
|
||||||
|
for (var i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
var t = FromType(args[i]);
|
||||||
|
if (t == null)
|
||||||
|
return null;
|
||||||
|
subTypes[i] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TRU(TRUIdentifier.Tuple7, nullable, null, subTypes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (type.IsArray)
|
||||||
|
{
|
||||||
|
var elementType = type.GetElementType();
|
||||||
|
if (elementType == typeof(object))
|
||||||
|
return new TRU(TRUIdentifier.List, nullable);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var subType = FromType(elementType);
|
||||||
|
|
||||||
|
if (subType == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new TRU(TRUIdentifier.TypedList, nullable, null,
|
||||||
|
new TRU[] { subType });
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type.IsEnum)
|
||||||
|
{
|
||||||
|
return new TRU(TRUIdentifier.Enum, nullable, TypeTemplate.GetTypeUUID(type));
|
||||||
|
}
|
||||||
|
else if (type.IsInterface)
|
||||||
|
{
|
||||||
|
return null; // other interfaces are not supported
|
||||||
|
}
|
||||||
|
|
||||||
|
//else if (typeof(Structure).IsAssignableFrom(t) || t == typeof(ExpandoObject) => TRUIdentifier.Structure)
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
_ when type == typeof(void) => new TRU(TRUIdentifier.Void, nullable),
|
||||||
|
_ when type == typeof(object) => new TRU(TRUIdentifier.Dynamic, nullable),
|
||||||
|
_ when type == typeof(bool) => new TRU(TRUIdentifier.Bool, nullable),
|
||||||
|
_ when type == typeof(char) => new TRU(TRUIdentifier.Char, nullable),
|
||||||
|
_ when type == typeof(byte) => new TRU(TRUIdentifier.UInt8, nullable),
|
||||||
|
_ when type == typeof(sbyte) => new TRU(TRUIdentifier.Int8, nullable),
|
||||||
|
_ when type == typeof(short) => new TRU(TRUIdentifier.Int16, nullable),
|
||||||
|
_ when type == typeof(ushort) => new TRU(TRUIdentifier.UInt16, nullable),
|
||||||
|
_ when type == typeof(int) => new TRU(TRUIdentifier.Int32, nullable),
|
||||||
|
_ when type == typeof(uint) => new TRU(TRUIdentifier.UInt32, nullable),
|
||||||
|
_ when type == typeof(long) => new TRU(TRUIdentifier.Int64, nullable),
|
||||||
|
_ when type == typeof(ulong) => new TRU(TRUIdentifier.UInt64, nullable),
|
||||||
|
_ when type == typeof(float) => new TRU(TRUIdentifier.Float32, nullable),
|
||||||
|
_ when type == typeof(double) => new TRU(TRUIdentifier.Float64, nullable),
|
||||||
|
_ when type == typeof(decimal) => new TRU(TRUIdentifier.Decimal, nullable),
|
||||||
|
_ when type == typeof(string) => new TRU(TRUIdentifier.String, nullable),
|
||||||
|
_ when type == typeof(DateTime) => new TRU(TRUIdentifier.DateTime, nullable),
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public TRU(TRUIdentifier identifier, bool nullable, UUID? uuid = null, TRU[]? subTypes = null)
|
||||||
|
{
|
||||||
|
Nullable = nullable;
|
||||||
|
Identifier = identifier;
|
||||||
|
UUID = uuid;
|
||||||
|
SubTypes = subTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Compose()
|
||||||
|
{
|
||||||
|
var rt = new BinaryList();
|
||||||
|
|
||||||
|
if (Nullable)
|
||||||
|
rt.AddUInt8((byte)(0x80 | (byte)Identifier));
|
||||||
|
else
|
||||||
|
rt.AddUInt8((byte)Identifier);
|
||||||
|
|
||||||
|
if (UUID != null)
|
||||||
|
rt.AddUInt8Array(UUID.Value.Data);
|
||||||
|
|
||||||
|
if (SubTypes != null)
|
||||||
|
for (var i = 0; i < SubTypes.Length; i++)
|
||||||
|
rt.AddUInt8Array(SubTypes[i].Compose());
|
||||||
|
|
||||||
|
return rt.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static (uint, TRU) Parse(byte[] data, uint offset)
|
||||||
|
{
|
||||||
|
var oOffset = offset;
|
||||||
|
|
||||||
|
var header = data[offset++];
|
||||||
|
bool nullable = (header & 0x80) > 0;
|
||||||
|
var identifier = (TRUIdentifier)(header & 0x7F);
|
||||||
|
|
||||||
|
|
||||||
|
if ((header & 0x40) > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
var hasUUID = (header & 0x4) > 0;
|
||||||
|
var subsCount = (header >> 3) & 0x7;
|
||||||
|
|
||||||
|
UUID? uuid = null;
|
||||||
|
|
||||||
|
if (hasUUID)
|
||||||
|
{
|
||||||
|
uuid = data.GetUUID(offset);
|
||||||
|
offset += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
var subs = new TRU[subsCount];
|
||||||
|
|
||||||
|
for (var i = 0; i < subsCount; i++)
|
||||||
|
{
|
||||||
|
(var len, subs[i]) = TRU.Parse(data, offset);
|
||||||
|
offset += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (offset - oOffset, new TRU(identifier, nullable, uuid, subs));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (1, new TRU(identifier, nullable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
46
Esiur/Data/TRUIdentifier.cs
Normal file
46
Esiur/Data/TRUIdentifier.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Esiur.Data
|
||||||
|
{
|
||||||
|
public enum TRUIdentifier
|
||||||
|
{
|
||||||
|
Void = 0x0,
|
||||||
|
Dynamic = 0x1,
|
||||||
|
Bool = 0x2,
|
||||||
|
UInt8,
|
||||||
|
Int8,
|
||||||
|
Char,
|
||||||
|
UInt16,
|
||||||
|
Int16,
|
||||||
|
UInt32,
|
||||||
|
Int32,
|
||||||
|
Float32,
|
||||||
|
UInt64,
|
||||||
|
Int64,
|
||||||
|
Float64,
|
||||||
|
DateTime,
|
||||||
|
UInt128,
|
||||||
|
Int128,
|
||||||
|
Decimal,
|
||||||
|
String,
|
||||||
|
RawData,
|
||||||
|
Resource,
|
||||||
|
Record,
|
||||||
|
List,
|
||||||
|
Map,
|
||||||
|
Enum = 0x44,
|
||||||
|
TypedResource = 0x45, // Followed by UUID
|
||||||
|
TypedRecord = 0x46, // Followed by UUID
|
||||||
|
TypedList = 0x48, // Followed by element type
|
||||||
|
Tuple2 = 0x50, // Followed by element type
|
||||||
|
TypedMap = 0x51, // Followed by key type and value type
|
||||||
|
Tuple3 = 0x58,
|
||||||
|
Tuple4 = 0x60,
|
||||||
|
Tuple5 = 0x68,
|
||||||
|
Tuple6 = 0x70,
|
||||||
|
Tuple7 = 0x78
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ namespace Esiur.Net.Packets
|
|||||||
// Success
|
// Success
|
||||||
Completed = 0x0,
|
Completed = 0x0,
|
||||||
Propagated = 0x1,
|
Propagated = 0x1,
|
||||||
|
Stream = 0x2,
|
||||||
|
|
||||||
// Error
|
// Error
|
||||||
PermissionError = 0x81,
|
PermissionError = 0x81,
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ namespace Esiur.Net.Packets
|
|||||||
// Request Static
|
// Request Static
|
||||||
KeepAlive = 0x18,
|
KeepAlive = 0x18,
|
||||||
ProcedureCall = 0x19,
|
ProcedureCall = 0x19,
|
||||||
StaticCall = 0x1A
|
StaticCall = 0x1A,
|
||||||
|
IndirectCall = 0x1B,
|
||||||
|
PullStream = 0x1C,
|
||||||
|
TerminateExecution = 0x1D,
|
||||||
|
HaltExecution = 0x1E,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,28 +121,28 @@ public static class TemplateGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static string GetTypeName(RepresentationType representationType, TypeTemplate[] templates)
|
static string GetTypeName(TRU representationType, TypeTemplate[] templates)
|
||||||
{
|
{
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
if (representationType.Identifier == RepresentationTypeIdentifier.TypedResource)// == DataType.Resource)
|
if (representationType.Identifier == TRUIdentifier.TypedResource)// == DataType.Resource)
|
||||||
name = templates.First(x => x.ClassId == representationType.UUID && (x.Type == TemplateType.Resource)).ClassName;
|
name = templates.First(x => x.ClassId == representationType.UUID && (x.Type == TemplateType.Resource)).ClassName;
|
||||||
else if (representationType.Identifier == RepresentationTypeIdentifier.TypedRecord)
|
else if (representationType.Identifier == TRUIdentifier.TypedRecord)
|
||||||
name = templates.First(x => x.ClassId == representationType.UUID && x.Type == TemplateType.Record).ClassName;
|
name = templates.First(x => x.ClassId == representationType.UUID && x.Type == TemplateType.Record).ClassName;
|
||||||
else if (representationType.Identifier == RepresentationTypeIdentifier.Enum)
|
else if (representationType.Identifier == TRUIdentifier.Enum)
|
||||||
name = templates.First(x => x.ClassId == representationType.UUID && x.Type == TemplateType.Enum).ClassName;
|
name = templates.First(x => x.ClassId == representationType.UUID && x.Type == TemplateType.Enum).ClassName;
|
||||||
else if (representationType.Identifier == RepresentationTypeIdentifier.TypedList)
|
else if (representationType.Identifier == TRUIdentifier.TypedList)
|
||||||
name = GetTypeName(representationType.SubTypes[0], templates) + "[]";
|
name = GetTypeName(representationType.SubTypes[0], templates) + "[]";
|
||||||
else if (representationType.Identifier == RepresentationTypeIdentifier.TypedMap)
|
else if (representationType.Identifier == TRUIdentifier.TypedMap)
|
||||||
name = "Map<" + GetTypeName(representationType.SubTypes[0], templates)
|
name = "Map<" + GetTypeName(representationType.SubTypes[0], templates)
|
||||||
+ "," + GetTypeName(representationType.SubTypes[1], templates)
|
+ "," + GetTypeName(representationType.SubTypes[1], templates)
|
||||||
+ ">";
|
+ ">";
|
||||||
else if (representationType.Identifier == RepresentationTypeIdentifier.Tuple2 ||
|
else if (representationType.Identifier == TRUIdentifier.Tuple2 ||
|
||||||
representationType.Identifier == RepresentationTypeIdentifier.Tuple3 ||
|
representationType.Identifier == TRUIdentifier.Tuple3 ||
|
||||||
representationType.Identifier == RepresentationTypeIdentifier.Tuple4 ||
|
representationType.Identifier == TRUIdentifier.Tuple4 ||
|
||||||
representationType.Identifier == RepresentationTypeIdentifier.Tuple5 ||
|
representationType.Identifier == TRUIdentifier.Tuple5 ||
|
||||||
representationType.Identifier == RepresentationTypeIdentifier.Tuple6 ||
|
representationType.Identifier == TRUIdentifier.Tuple6 ||
|
||||||
representationType.Identifier == RepresentationTypeIdentifier.Tuple7)
|
representationType.Identifier == TRUIdentifier.Tuple7)
|
||||||
name = "(" + String.Join(",", representationType.SubTypes.Select(x => GetTypeName(x, templates)))
|
name = "(" + String.Join(",", representationType.SubTypes.Select(x => GetTypeName(x, templates)))
|
||||||
+ ")";
|
+ ")";
|
||||||
else
|
else
|
||||||
@@ -150,26 +150,26 @@ public static class TemplateGenerator
|
|||||||
|
|
||||||
name = representationType.Identifier switch
|
name = representationType.Identifier switch
|
||||||
{
|
{
|
||||||
RepresentationTypeIdentifier.Dynamic => "object",
|
TRUIdentifier.Dynamic => "object",
|
||||||
RepresentationTypeIdentifier.Bool => "bool",
|
TRUIdentifier.Bool => "bool",
|
||||||
RepresentationTypeIdentifier.Char => "char",
|
TRUIdentifier.Char => "char",
|
||||||
RepresentationTypeIdentifier.DateTime => "DateTime",
|
TRUIdentifier.DateTime => "DateTime",
|
||||||
RepresentationTypeIdentifier.Decimal => "decimal",
|
TRUIdentifier.Decimal => "decimal",
|
||||||
RepresentationTypeIdentifier.Float32 => "float",
|
TRUIdentifier.Float32 => "float",
|
||||||
RepresentationTypeIdentifier.Float64 => "double",
|
TRUIdentifier.Float64 => "double",
|
||||||
RepresentationTypeIdentifier.Int16 => "short",
|
TRUIdentifier.Int16 => "short",
|
||||||
RepresentationTypeIdentifier.Int32 => "int",
|
TRUIdentifier.Int32 => "int",
|
||||||
RepresentationTypeIdentifier.Int64 => "long",
|
TRUIdentifier.Int64 => "long",
|
||||||
RepresentationTypeIdentifier.Int8 => "sbyte",
|
TRUIdentifier.Int8 => "sbyte",
|
||||||
RepresentationTypeIdentifier.String => "string",
|
TRUIdentifier.String => "string",
|
||||||
RepresentationTypeIdentifier.Map => "Map<object, object>",
|
TRUIdentifier.Map => "Map<object, object>",
|
||||||
RepresentationTypeIdentifier.UInt16 => "ushort",
|
TRUIdentifier.UInt16 => "ushort",
|
||||||
RepresentationTypeIdentifier.UInt32 => "uint",
|
TRUIdentifier.UInt32 => "uint",
|
||||||
RepresentationTypeIdentifier.UInt64 => "ulong",
|
TRUIdentifier.UInt64 => "ulong",
|
||||||
RepresentationTypeIdentifier.UInt8 => "byte",
|
TRUIdentifier.UInt8 => "byte",
|
||||||
RepresentationTypeIdentifier.List => "object[]",
|
TRUIdentifier.List => "object[]",
|
||||||
RepresentationTypeIdentifier.Resource => "IResource",
|
TRUIdentifier.Resource => "IResource",
|
||||||
RepresentationTypeIdentifier.Record => "IRecord",
|
TRUIdentifier.Record => "IRecord",
|
||||||
_ => "object"
|
_ => "object"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class Storable : global::System.Attribute
|
|||||||
|
|
||||||
SerializerFunction serializer;
|
SerializerFunction serializer;
|
||||||
DeserializerFunction deserializer;
|
DeserializerFunction deserializer;
|
||||||
RepresentationType dataType;
|
TRU dataType;
|
||||||
|
|
||||||
public Storable()
|
public Storable()
|
||||||
{
|
{
|
||||||
@@ -57,12 +57,12 @@ public class Storable : global::System.Attribute
|
|||||||
get { return serializer; }
|
get { return serializer; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Storable(RepresentationType type)
|
public Storable(TRU type)
|
||||||
{
|
{
|
||||||
this.dataType = type;
|
this.dataType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Storable(RepresentationType type, SerializerFunction serializer, DeserializerFunction deserializer)
|
public Storable(TRU type, SerializerFunction serializer, DeserializerFunction deserializer)
|
||||||
{
|
{
|
||||||
this.dataType = type;
|
this.dataType = type;
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class ArgumentTemplate
|
|||||||
|
|
||||||
public bool Optional { get; set; }
|
public bool Optional { get; set; }
|
||||||
|
|
||||||
public RepresentationType Type { get; set; }
|
public TRU Type { get; set; }
|
||||||
|
|
||||||
public ParameterInfo ParameterInfo { get; set; }
|
public ParameterInfo ParameterInfo { get; set; }
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ public class ArgumentTemplate
|
|||||||
var cs = (uint)data[offset++];
|
var cs = (uint)data[offset++];
|
||||||
var name = data.GetString(offset, cs);
|
var name = data.GetString(offset, cs);
|
||||||
offset += cs;
|
offset += cs;
|
||||||
var (size, type) = RepresentationType.Parse(data, offset);
|
var (size, type) = TRU.Parse(data, offset);
|
||||||
|
|
||||||
return (cs + 2 + size, new ArgumentTemplate(name, index, type, optional));
|
return (cs + 2 + size, new ArgumentTemplate(name, index, type, optional));
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@ public class ArgumentTemplate
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArgumentTemplate(string name, int index, RepresentationType type, bool optional)
|
public ArgumentTemplate(string name, int index, TRU type, bool optional)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
Index = index;
|
Index = index;
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ public class ConstantTemplate : MemberTemplate
|
|||||||
public readonly object Value;
|
public readonly object Value;
|
||||||
//public readonly byte[] ValueData;
|
//public readonly byte[] ValueData;
|
||||||
public readonly string Annotation;
|
public readonly string Annotation;
|
||||||
public readonly RepresentationType ValueType;
|
public readonly TRU ValueType;
|
||||||
|
|
||||||
public FieldInfo FieldInfo { get; set; }
|
public FieldInfo FieldInfo { get; set; }
|
||||||
|
|
||||||
public ConstantTemplate(TypeTemplate template, byte index, string name, bool inherited, RepresentationType valueType, object value, string annotation)
|
public ConstantTemplate(TypeTemplate template, byte index, string name, bool inherited, TRU valueType, object value, string annotation)
|
||||||
: base(template, index, name, inherited)
|
: base(template, index, name, inherited)
|
||||||
{
|
{
|
||||||
Annotation = annotation;
|
Annotation = annotation;
|
||||||
@@ -73,7 +73,7 @@ public class ConstantTemplate : MemberTemplate
|
|||||||
{
|
{
|
||||||
var annotationAttr = ci.GetCustomAttribute<AnnotationAttribute>(true);
|
var annotationAttr = ci.GetCustomAttribute<AnnotationAttribute>(true);
|
||||||
|
|
||||||
var valueType = RepresentationType.FromType(ci.FieldType);
|
var valueType = TRU.FromType(ci.FieldType);
|
||||||
|
|
||||||
if (valueType == null)
|
if (valueType == null)
|
||||||
throw new Exception($"Unsupported type `{ci.FieldType}` in constant `{type.Name}.{ci.Name}`");
|
throw new Exception($"Unsupported type `{ci.FieldType}` in constant `{type.Name}.{ci.Name}`");
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class EventTemplate : MemberTemplate
|
|||||||
|
|
||||||
public EventInfo EventInfo { get; set; }
|
public EventInfo EventInfo { get; set; }
|
||||||
|
|
||||||
public RepresentationType ArgumentType { get; set; }
|
public TRU ArgumentType { get; set; }
|
||||||
|
|
||||||
public override byte[] Compose()
|
public override byte[] Compose()
|
||||||
{
|
{
|
||||||
@@ -55,7 +55,7 @@ public class EventTemplate : MemberTemplate
|
|||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventTemplate(TypeTemplate template, byte index, string name, bool inherited, RepresentationType argumentType, string annotation = null, bool subscribable = false)
|
public EventTemplate(TypeTemplate template, byte index, string name, bool inherited, TRU argumentType, string annotation = null, bool subscribable = false)
|
||||||
: base(template, index, name, inherited)
|
: base(template, index, name, inherited)
|
||||||
{
|
{
|
||||||
this.Annotation = annotation;
|
this.Annotation = annotation;
|
||||||
@@ -75,7 +75,7 @@ public class EventTemplate : MemberTemplate
|
|||||||
|
|
||||||
|
|
||||||
var argType = ei.EventHandlerType.GenericTypeArguments[0];
|
var argType = ei.EventHandlerType.GenericTypeArguments[0];
|
||||||
var evtType = RepresentationType.FromType(argType);
|
var evtType = TRU.FromType(argType);
|
||||||
|
|
||||||
if (evtType == null)
|
if (evtType == null)
|
||||||
throw new Exception($"Unsupported type `{argType}` in event `{type.Name}.{ei.Name}`");
|
throw new Exception($"Unsupported type `{argType}` in event `{type.Name}.{ei.Name}`");
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class FunctionTemplate : MemberTemplate
|
|||||||
// set;
|
// set;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
public RepresentationType ReturnType { get; set; }
|
public TRU ReturnType { get; set; }
|
||||||
|
|
||||||
public bool IsStatic { get; set; }
|
public bool IsStatic { get; set; }
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ public class FunctionTemplate : MemberTemplate
|
|||||||
return bl.ToArray();
|
return bl.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FunctionTemplate(TypeTemplate template, byte index, string name, bool inherited, bool isStatic, ArgumentTemplate[] arguments, RepresentationType returnType, string annotation = null)
|
public FunctionTemplate(TypeTemplate template, byte index, string name, bool inherited, bool isStatic, ArgumentTemplate[] arguments, TRU returnType, string annotation = null)
|
||||||
: base(template, index, name, inherited)
|
: base(template, index, name, inherited)
|
||||||
{
|
{
|
||||||
this.Arguments = arguments;
|
this.Arguments = arguments;
|
||||||
@@ -82,20 +82,20 @@ public class FunctionTemplate : MemberTemplate
|
|||||||
|
|
||||||
var genericRtType = mi.ReturnType.IsGenericType ? mi.ReturnType.GetGenericTypeDefinition() : null;
|
var genericRtType = mi.ReturnType.IsGenericType ? mi.ReturnType.GetGenericTypeDefinition() : null;
|
||||||
|
|
||||||
RepresentationType rtType;
|
TRU rtType;
|
||||||
|
|
||||||
if (genericRtType == typeof(AsyncReply<>))
|
if (genericRtType == typeof(AsyncReply<>))
|
||||||
{
|
{
|
||||||
rtType = RepresentationType.FromType(mi.ReturnType.GetGenericArguments()[0]);
|
rtType = TRU.FromType(mi.ReturnType.GetGenericArguments()[0]);
|
||||||
}
|
}
|
||||||
else if (genericRtType == typeof(IEnumerable<>))// || genericRtType == typeof(IAsyncEnumerable<>))
|
else if (genericRtType == typeof(IEnumerable<>))// || genericRtType == typeof(IAsyncEnumerable<>))
|
||||||
{
|
{
|
||||||
// get export
|
// get export
|
||||||
rtType = RepresentationType.FromType(mi.ReturnType.GetGenericArguments()[0]);
|
rtType = TRU.FromType(mi.ReturnType.GetGenericArguments()[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rtType = RepresentationType.FromType(mi.ReturnType);
|
rtType = TRU.FromType(mi.ReturnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtType == null)
|
if (rtType == null)
|
||||||
@@ -165,7 +165,7 @@ public class FunctionTemplate : MemberTemplate
|
|||||||
|
|
||||||
var arguments = args.Select(x =>
|
var arguments = args.Select(x =>
|
||||||
{
|
{
|
||||||
var argType = RepresentationType.FromType(x.ParameterType);
|
var argType = TRU.FromType(x.ParameterType);
|
||||||
|
|
||||||
if (argType == null)
|
if (argType == null)
|
||||||
throw new Exception($"Unsupported type `{x.ParameterType}` in method `{type.Name}.{mi.Name}` parameter `{x.Name}`");
|
throw new Exception($"Unsupported type `{x.ParameterType}` in method `{type.Name}.{mi.Name}` parameter `{x.Name}`");
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class PropertyTemplate : MemberTemplate
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RepresentationType ValueType { get; set; }
|
public TRU ValueType { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -136,7 +136,7 @@ public class PropertyTemplate : MemberTemplate
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PropertyTemplate(TypeTemplate template, byte index, string name, bool inherited,
|
public PropertyTemplate(TypeTemplate template, byte index, string name, bool inherited,
|
||||||
RepresentationType valueType, string readAnnotation = null, string writeAnnotation = null, bool recordable = false)
|
TRU valueType, string readAnnotation = null, string writeAnnotation = null, bool recordable = false)
|
||||||
: base(template, index, name, inherited)
|
: base(template, index, name, inherited)
|
||||||
{
|
{
|
||||||
this.Recordable = recordable;
|
this.Recordable = recordable;
|
||||||
@@ -152,8 +152,8 @@ public class PropertyTemplate : MemberTemplate
|
|||||||
var genericPropType = pi.PropertyType.IsGenericType ? pi.PropertyType.GetGenericTypeDefinition() : null;
|
var genericPropType = pi.PropertyType.IsGenericType ? pi.PropertyType.GetGenericTypeDefinition() : null;
|
||||||
|
|
||||||
var propType = genericPropType == typeof(PropertyContext<>) ?
|
var propType = genericPropType == typeof(PropertyContext<>) ?
|
||||||
RepresentationType.FromType(pi.PropertyType.GetGenericArguments()[0]) :
|
TRU.FromType(pi.PropertyType.GetGenericArguments()[0]) :
|
||||||
RepresentationType.FromType(pi.PropertyType);
|
TRU.FromType(pi.PropertyType);
|
||||||
|
|
||||||
if (propType == null)
|
if (propType == null)
|
||||||
throw new Exception($"Unsupported type `{pi.PropertyType}` in property `{type.Name}.{pi.Name}`");
|
throw new Exception($"Unsupported type `{pi.PropertyType}` in property `{type.Name}.{pi.Name}`");
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ public class TypeTemplate
|
|||||||
{
|
{
|
||||||
var annotationAttr = ci.GetCustomAttribute<AnnotationAttribute>(true);
|
var annotationAttr = ci.GetCustomAttribute<AnnotationAttribute>(true);
|
||||||
|
|
||||||
var valueType = RepresentationType.FromType(ci.FieldType);
|
var valueType = TRU.FromType(ci.FieldType);
|
||||||
|
|
||||||
if (valueType == null)
|
if (valueType == null)
|
||||||
throw new Exception($"Unsupported type `{ci.FieldType}` in constant `{type.Name}.{ci.Name}`");
|
throw new Exception($"Unsupported type `{ci.FieldType}` in constant `{type.Name}.{ci.Name}`");
|
||||||
@@ -783,7 +783,7 @@ public class TypeTemplate
|
|||||||
offset += (uint)data[offset] + 1;
|
offset += (uint)data[offset] + 1;
|
||||||
|
|
||||||
// return type
|
// return type
|
||||||
var (rts, returnType) = RepresentationType.Parse(data, offset);
|
var (rts, returnType) = TRU.Parse(data, offset);
|
||||||
offset += rts;
|
offset += rts;
|
||||||
|
|
||||||
// arguments count
|
// arguments count
|
||||||
@@ -823,7 +823,7 @@ public class TypeTemplate
|
|||||||
|
|
||||||
offset += (uint)data[offset] + 1;
|
offset += (uint)data[offset] + 1;
|
||||||
|
|
||||||
var (dts, valueType) = RepresentationType.Parse(data, offset);
|
var (dts, valueType) = TRU.Parse(data, offset);
|
||||||
|
|
||||||
offset += dts;
|
offset += dts;
|
||||||
|
|
||||||
@@ -857,7 +857,7 @@ public class TypeTemplate
|
|||||||
var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, (int)data[offset]);
|
var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, (int)data[offset]);
|
||||||
offset += (uint)data[offset] + 1;
|
offset += (uint)data[offset] + 1;
|
||||||
|
|
||||||
var (dts, argType) = RepresentationType.Parse(data, offset);
|
var (dts, argType) = TRU.Parse(data, offset);
|
||||||
|
|
||||||
offset += dts;
|
offset += dts;
|
||||||
|
|
||||||
@@ -883,7 +883,7 @@ public class TypeTemplate
|
|||||||
var name = data.GetString(offset + 1, data[offset]);
|
var name = data.GetString(offset + 1, data[offset]);
|
||||||
offset += (uint)data[offset] + 1;
|
offset += (uint)data[offset] + 1;
|
||||||
|
|
||||||
var (dts, valueType) = RepresentationType.Parse(data, offset);
|
var (dts, valueType) = TRU.Parse(data, offset);
|
||||||
|
|
||||||
offset += dts;
|
offset += dts;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user