mirror of
				https://github.com/esiur/esiur-dotnet.git
				synced 2025-10-30 23:51:34 +00:00 
			
		
		
		
	Pull Stream
This commit is contained in:
		| @@ -381,7 +381,7 @@ public static class Codec | ||||
|         ComposeInternal(object valueOrSource, Warehouse warehouse, DistributedConnection connection) | ||||
|     { | ||||
|         if (valueOrSource == null) | ||||
|             return new TDU(TDUIdentifier.Null); | ||||
|             return new TDU(TDUIdentifier.Null, null, 0); | ||||
|  | ||||
|         var type = valueOrSource.GetType(); | ||||
|  | ||||
| @@ -408,7 +408,7 @@ public static class Codec | ||||
|             valueOrSource = ((IUserType)valueOrSource).Get(); | ||||
|  | ||||
|         if (valueOrSource == null) | ||||
|             return new TDU(TDUIdentifier.Null); | ||||
|             return new TDU(TDUIdentifier.Null, null, 0); | ||||
|  | ||||
|  | ||||
|         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.Core; | ||||
| using Esiur.Resource; | ||||
| using System.Collections; | ||||
| using Esiur.Data.GVWIE; | ||||
|  | ||||
| namespace Esiur.Data; | ||||
|  | ||||
| public static class DC // Data Converter | ||||
| { | ||||
|  | ||||
|  | ||||
|     public static object CastConvert(object value, Type destinationType) | ||||
|     { | ||||
|         if (value == null) | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using Esiur.Core; | ||||
| using Esiur.Data; | ||||
| using Esiur.Data.GVWIE; | ||||
| using Esiur.Misc; | ||||
| using Esiur.Net.IIP; | ||||
| using Esiur.Resource; | ||||
| @@ -742,8 +743,8 @@ public static class DataDeserializer | ||||
|     { | ||||
|         // get key type | ||||
|  | ||||
|         var (keyCs, keyRepType) = RepresentationType.Parse(tdu.Metadata, 0); | ||||
|         var (valueCs, valueRepType) = RepresentationType.Parse(tdu.Metadata, keyCs); | ||||
|         var (keyCs, keyRepType) = TRU.Parse(tdu.Metadata, 0); | ||||
|         var (valueCs, valueRepType) = TRU.Parse(tdu.Metadata, keyCs); | ||||
|  | ||||
|         var wh = connection.Instance.Warehouse; | ||||
|  | ||||
| @@ -792,8 +793,8 @@ public static class DataDeserializer | ||||
|     { | ||||
|         // get key type | ||||
|  | ||||
|         var (keyCs, keyRepType) = RepresentationType.Parse(tdu.Metadata, 0); | ||||
|         var (valueCs, valueRepType) = RepresentationType.Parse(tdu.Metadata, keyCs); | ||||
|         var (keyCs, keyRepType) = TRU.Parse(tdu.Metadata, 0); | ||||
|         var (valueCs, valueRepType) = TRU.Parse(tdu.Metadata, keyCs); | ||||
|  | ||||
|         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; | ||||
|         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)); | ||||
|             mtOffset += cs; | ||||
|         } | ||||
| @@ -913,7 +914,7 @@ public static class DataDeserializer | ||||
|         uint mtOffset = 1; | ||||
|         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)); | ||||
|             mtOffset += cs; | ||||
|         } | ||||
| @@ -975,111 +976,152 @@ public static class DataDeserializer | ||||
|  | ||||
|     public static AsyncReply TypedListParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence) | ||||
|     { | ||||
|         var rt = new AsyncBag<object>(); | ||||
|  | ||||
|         // get the type | ||||
|         var (hdrCs, rep) = RepresentationType.Parse(tdu.Metadata, 0); | ||||
|         var (hdrCs, rep) = TRU.Parse(tdu.Metadata, 0); | ||||
|  | ||||
|  | ||||
|         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) | ||||
|         switch (rep.Identifier) | ||||
|         { | ||||
|             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) | ||||
|                 throw new Exception("Unknown type."); | ||||
|                 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) | ||||
|                 { | ||||
|  | ||||
|                     current = ParsedTDU.Parse(tdu.Data, offset, ends); | ||||
|  | ||||
|                     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; | ||||
|             } | ||||
|                     if (current.Identifier == TDUIdentifier.TypeContinuation) | ||||
|                     { | ||||
|                         current.Class = previous.Value.Class; | ||||
|                         current.Identifier = previous.Value.Identifier; | ||||
|                         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) | ||||
|             { | ||||
|                 offset += (uint)cs; | ||||
|                 length -= (uint)cs; | ||||
|             } | ||||
|             else | ||||
|                 throw new Exception("Error while parsing structured data"); | ||||
|                     if (cs > 0) | ||||
|                     { | ||||
|                         offset += (uint)cs; | ||||
|                         length -= (uint)cs; | ||||
|                     } | ||||
|                     else | ||||
|                         throw new Exception("Error while parsing structured data"); | ||||
|  | ||||
|                 } | ||||
|  | ||||
|                 rt.Seal(); | ||||
|                 return rt; | ||||
|         } | ||||
|  | ||||
|         rt.Seal(); | ||||
|         return rt; | ||||
|     } | ||||
|  | ||||
|     public static object TypedListParser(ParsedTDU tdu, Warehouse warehouse) | ||||
|     { | ||||
|  | ||||
|         // get the type | ||||
|         var (hdrCs, rep) = RepresentationType.Parse(tdu.Metadata, 0); | ||||
|         var (hdrCs, rep) = TRU.Parse(tdu.Metadata, 0); | ||||
|  | ||||
|         //offset += hdrCs; | ||||
|         //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) | ||||
|         switch (rep.Identifier) | ||||
|         { | ||||
|             current = ParsedTDU.Parse(tdu.Data, offset, ends); | ||||
|  | ||||
|             if (current.Class == TDUClass.Invalid) | ||||
|                 throw new Exception("Unknown type."); | ||||
|             case TRUIdentifier.Int32: | ||||
|                 return GroupInt32Codec.Decode(tdu.Data.AsSpan( | ||||
|                                                     (int)tdu.Offset, (int)tdu.ContentLength)); | ||||
|             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) | ||||
|             { | ||||
|                 current.Class = previous.Value.Class; | ||||
|                 current.Identifier = previous.Value.Identifier; | ||||
|                 current.Metadata = previous.Value.Metadata; | ||||
|             } | ||||
|                 var list = new List<object>(); | ||||
|  | ||||
|             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) | ||||
|             { | ||||
|                 offset += (uint)cs; | ||||
|                 length -= (uint)cs; | ||||
|                 previous = current; | ||||
|             } | ||||
|             else | ||||
|                 throw new Exception("Error while parsing structured data"); | ||||
|                 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) | ||||
|                     { | ||||
|                         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) | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using Esiur.Core; | ||||
| using Esiur.Data.GVWIE; | ||||
| using Esiur.Net.IIP; | ||||
| using Esiur.Resource; | ||||
| 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; | ||||
|  | ||||
| @@ -404,6 +405,7 @@ public static class DataSerializer | ||||
|         if (ct == null) | ||||
|             return new TDU(TDUIdentifier.Null, null, 0); | ||||
|  | ||||
|         return Codec.ComposeInternal(intVal, warehouse, connection); | ||||
|  | ||||
|         return new TDU(TDUIdentifier.TypedEnum, | ||||
|             new byte[] { ct.Index }, 1, template.ClassId.Data); | ||||
| @@ -442,18 +444,18 @@ public static class DataSerializer | ||||
|     { | ||||
|         if ((bool)value) | ||||
|         { | ||||
|             return new TDU(TDUIdentifier.True); | ||||
|             return new TDU(TDUIdentifier.True, null, 0); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return new TDU(TDUIdentifier.True); | ||||
|             return new TDU(TDUIdentifier.True, null, 0); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     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) | ||||
| @@ -492,16 +494,85 @@ public static class DataSerializer | ||||
|  | ||||
|     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) | ||||
|             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) | ||||
| @@ -539,8 +610,8 @@ public static class DataSerializer | ||||
|         if (value == null) | ||||
|             return new TDU(TDUIdentifier.Null, new byte[0], 0); | ||||
|  | ||||
|         var kt = RepresentationType.FromType(keyType).Compose(); | ||||
|         var vt = RepresentationType.FromType(valueType).Compose(); | ||||
|         var kt = TRU.FromType(keyType).Compose(); | ||||
|         var vt = TRU.FromType(valueType).Compose(); | ||||
|  | ||||
|         var rt = new List<byte>(); | ||||
|  | ||||
| @@ -558,8 +629,8 @@ public static class DataSerializer | ||||
|         if (value == null) | ||||
|             return new TDU(TDUIdentifier.Null, null, 0); | ||||
|  | ||||
|         var kt = RepresentationType.FromType(keyType).Compose(); | ||||
|         var vt = RepresentationType.FromType(valueType).Compose(); | ||||
|         var kt = TRU.FromType(keyType).Compose(); | ||||
|         var vt = TRU.FromType(valueType).Compose(); | ||||
|  | ||||
|         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)); | ||||
|     } | ||||
|  | ||||
|     public static byte[] ArrayComposer(IEnumerable value, Warehouse warehouse, DistributedConnection connection) | ||||
|     public static byte[] DynamicArrayComposer(IEnumerable value, Warehouse warehouse, DistributedConnection connection) | ||||
|     { | ||||
|         if (value == null) | ||||
|             return null; | ||||
| @@ -727,14 +798,29 @@ public static class DataSerializer | ||||
|         foreach (var pt in template.Properties) | ||||
|         { | ||||
|             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(), | ||||
|             (uint)rt.Count, | ||||
|             template.ClassId.Data); | ||||
|     } | ||||
|  | ||||
|     public static byte[] HistoryComposer(KeyList<PropertyTemplate, PropertyValue[]> history, Warehouse warehouse, | ||||
|                                         DistributedConnection connection, bool prependLength = false) | ||||
|     { | ||||
| @@ -758,7 +844,7 @@ public static class DataSerializer | ||||
|  | ||||
|         var fields = value.GetType().GetFields(); | ||||
|         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>(); | ||||
|   | ||||
							
								
								
									
										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) | ||||
|     { | ||||
|         Identifier = identifier; | ||||
|         Composed = new byte[0]; | ||||
|     } | ||||
|  | ||||
|     public TDU(TDUIdentifier identifier, | ||||
| @@ -74,7 +75,10 @@ public struct TDU | ||||
|  | ||||
|         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 | ||||
|             || Class == TDUClass.Extension) | ||||
|   | ||||
| @@ -58,7 +58,7 @@ namespace Esiur.Data | ||||
|         TypedConstant = 0x85, | ||||
|  | ||||
|         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 | ||||
|         Completed = 0x0, | ||||
|         Propagated = 0x1, | ||||
|         Stream = 0x2, | ||||
|  | ||||
|         // Error | ||||
|         PermissionError = 0x81, | ||||
|   | ||||
| @@ -32,6 +32,11 @@ namespace Esiur.Net.Packets | ||||
|         // Request Static | ||||
|         KeepAlive = 0x18, | ||||
|         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; | ||||
|  | ||||
|         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; | ||||
|         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; | ||||
|         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; | ||||
|         else if (representationType.Identifier == RepresentationTypeIdentifier.TypedList) | ||||
|         else if (representationType.Identifier == TRUIdentifier.TypedList) | ||||
|             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) | ||||
|                     + "," + GetTypeName(representationType.SubTypes[1], templates) | ||||
|                     + ">"; | ||||
|         else if (representationType.Identifier == RepresentationTypeIdentifier.Tuple2 || | ||||
|                  representationType.Identifier == RepresentationTypeIdentifier.Tuple3 || | ||||
|                  representationType.Identifier == RepresentationTypeIdentifier.Tuple4 || | ||||
|                  representationType.Identifier == RepresentationTypeIdentifier.Tuple5 || | ||||
|                  representationType.Identifier == RepresentationTypeIdentifier.Tuple6 || | ||||
|                  representationType.Identifier == RepresentationTypeIdentifier.Tuple7) | ||||
|         else if (representationType.Identifier == TRUIdentifier.Tuple2 || | ||||
|                  representationType.Identifier == TRUIdentifier.Tuple3 || | ||||
|                  representationType.Identifier == TRUIdentifier.Tuple4 || | ||||
|                  representationType.Identifier == TRUIdentifier.Tuple5 || | ||||
|                  representationType.Identifier == TRUIdentifier.Tuple6 || | ||||
|                  representationType.Identifier == TRUIdentifier.Tuple7) | ||||
|             name = "(" + String.Join(",", representationType.SubTypes.Select(x => GetTypeName(x, templates))) | ||||
|                     + ")"; | ||||
|         else | ||||
| @@ -150,26 +150,26 @@ public static class TemplateGenerator | ||||
|  | ||||
|             name = representationType.Identifier switch | ||||
|             { | ||||
|                 RepresentationTypeIdentifier.Dynamic => "object", | ||||
|                 RepresentationTypeIdentifier.Bool => "bool", | ||||
|                 RepresentationTypeIdentifier.Char => "char", | ||||
|                 RepresentationTypeIdentifier.DateTime => "DateTime", | ||||
|                 RepresentationTypeIdentifier.Decimal => "decimal", | ||||
|                 RepresentationTypeIdentifier.Float32 => "float", | ||||
|                 RepresentationTypeIdentifier.Float64 => "double", | ||||
|                 RepresentationTypeIdentifier.Int16 => "short", | ||||
|                 RepresentationTypeIdentifier.Int32 => "int", | ||||
|                 RepresentationTypeIdentifier.Int64 => "long", | ||||
|                 RepresentationTypeIdentifier.Int8 => "sbyte", | ||||
|                 RepresentationTypeIdentifier.String => "string", | ||||
|                 RepresentationTypeIdentifier.Map => "Map<object, object>", | ||||
|                 RepresentationTypeIdentifier.UInt16 => "ushort", | ||||
|                 RepresentationTypeIdentifier.UInt32 => "uint", | ||||
|                 RepresentationTypeIdentifier.UInt64 => "ulong", | ||||
|                 RepresentationTypeIdentifier.UInt8 => "byte", | ||||
|                 RepresentationTypeIdentifier.List => "object[]", | ||||
|                 RepresentationTypeIdentifier.Resource => "IResource", | ||||
|                 RepresentationTypeIdentifier.Record => "IRecord", | ||||
|                 TRUIdentifier.Dynamic => "object", | ||||
|                 TRUIdentifier.Bool => "bool", | ||||
|                 TRUIdentifier.Char => "char", | ||||
|                 TRUIdentifier.DateTime => "DateTime", | ||||
|                 TRUIdentifier.Decimal => "decimal", | ||||
|                 TRUIdentifier.Float32 => "float", | ||||
|                 TRUIdentifier.Float64 => "double", | ||||
|                 TRUIdentifier.Int16 => "short", | ||||
|                 TRUIdentifier.Int32 => "int", | ||||
|                 TRUIdentifier.Int64 => "long", | ||||
|                 TRUIdentifier.Int8 => "sbyte", | ||||
|                 TRUIdentifier.String => "string", | ||||
|                 TRUIdentifier.Map => "Map<object, object>", | ||||
|                 TRUIdentifier.UInt16 => "ushort", | ||||
|                 TRUIdentifier.UInt32 => "uint", | ||||
|                 TRUIdentifier.UInt64 => "ulong", | ||||
|                 TRUIdentifier.UInt8 => "byte", | ||||
|                 TRUIdentifier.List => "object[]", | ||||
|                 TRUIdentifier.Resource => "IResource", | ||||
|                 TRUIdentifier.Record => "IRecord", | ||||
|                 _ => "object" | ||||
|             }; | ||||
|         } | ||||
|   | ||||
| @@ -40,7 +40,7 @@ public class Storable : global::System.Attribute | ||||
|  | ||||
|     SerializerFunction serializer; | ||||
|     DeserializerFunction deserializer; | ||||
|     RepresentationType dataType; | ||||
|     TRU dataType; | ||||
|  | ||||
|     public Storable() | ||||
|     { | ||||
| @@ -57,12 +57,12 @@ public class Storable : global::System.Attribute | ||||
|         get { return serializer; } | ||||
|     } | ||||
|  | ||||
|     public Storable(RepresentationType type) | ||||
|     public Storable(TRU type) | ||||
|     { | ||||
|         this.dataType = type; | ||||
|     } | ||||
|  | ||||
|     public Storable(RepresentationType type, SerializerFunction serializer, DeserializerFunction deserializer) | ||||
|     public Storable(TRU type, SerializerFunction serializer, DeserializerFunction deserializer) | ||||
|     { | ||||
|         this.dataType = type; | ||||
|         this.serializer = serializer; | ||||
|   | ||||
| @@ -11,7 +11,7 @@ public class ArgumentTemplate | ||||
|  | ||||
|     public bool Optional { get; set; } | ||||
|  | ||||
|     public RepresentationType Type { get; set; } | ||||
|     public TRU Type { get; set; } | ||||
|  | ||||
|     public ParameterInfo ParameterInfo { get; set; } | ||||
|  | ||||
| @@ -24,7 +24,7 @@ public class ArgumentTemplate | ||||
|         var cs = (uint)data[offset++]; | ||||
|         var name = data.GetString(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)); | ||||
|     } | ||||
| @@ -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; | ||||
|         Index = index; | ||||
|   | ||||
| @@ -12,11 +12,11 @@ public class ConstantTemplate : MemberTemplate | ||||
|     public readonly object Value; | ||||
|     //public readonly byte[] ValueData; | ||||
|     public readonly string Annotation; | ||||
|     public readonly RepresentationType ValueType; | ||||
|     public readonly TRU ValueType; | ||||
|  | ||||
|     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) | ||||
|     { | ||||
|         Annotation = annotation; | ||||
| @@ -73,7 +73,7 @@ public class ConstantTemplate : MemberTemplate | ||||
|     { | ||||
|         var annotationAttr = ci.GetCustomAttribute<AnnotationAttribute>(true); | ||||
|  | ||||
|         var valueType = RepresentationType.FromType(ci.FieldType); | ||||
|         var valueType = TRU.FromType(ci.FieldType); | ||||
|  | ||||
|         if (valueType == null) | ||||
|             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 RepresentationType ArgumentType { get; set; } | ||||
|     public TRU ArgumentType { get; set; } | ||||
|  | ||||
|     public override byte[] Compose() | ||||
|     { | ||||
| @@ -55,7 +55,7 @@ public class EventTemplate : MemberTemplate | ||||
|                 .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) | ||||
|     { | ||||
|         this.Annotation = annotation; | ||||
| @@ -75,7 +75,7 @@ public class EventTemplate : MemberTemplate | ||||
|  | ||||
|  | ||||
|         var argType = ei.EventHandlerType.GenericTypeArguments[0]; | ||||
|         var evtType = RepresentationType.FromType(argType); | ||||
|         var evtType = TRU.FromType(argType); | ||||
|  | ||||
|         if (evtType == null) | ||||
|             throw new Exception($"Unsupported type `{argType}` in event `{type.Name}.{ei.Name}`"); | ||||
|   | ||||
| @@ -25,7 +25,7 @@ public class FunctionTemplate : MemberTemplate | ||||
|     //    set; | ||||
|     //} | ||||
|  | ||||
|     public RepresentationType ReturnType { get; set; } | ||||
|     public TRU ReturnType { get; set; } | ||||
|  | ||||
|     public bool IsStatic { get; set; } | ||||
|  | ||||
| @@ -66,7 +66,7 @@ public class FunctionTemplate : MemberTemplate | ||||
|         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) | ||||
|     { | ||||
|         this.Arguments = arguments; | ||||
| @@ -82,20 +82,20 @@ public class FunctionTemplate : MemberTemplate | ||||
|  | ||||
|         var genericRtType = mi.ReturnType.IsGenericType ? mi.ReturnType.GetGenericTypeDefinition() : null; | ||||
|  | ||||
|         RepresentationType rtType; | ||||
|         TRU rtType; | ||||
|  | ||||
|         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<>)) | ||||
|         { | ||||
|             // get export | ||||
|             rtType = RepresentationType.FromType(mi.ReturnType.GetGenericArguments()[0]); | ||||
|             rtType = TRU.FromType(mi.ReturnType.GetGenericArguments()[0]); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             rtType = RepresentationType.FromType(mi.ReturnType); | ||||
|             rtType = TRU.FromType(mi.ReturnType); | ||||
|         } | ||||
|  | ||||
|         if (rtType == null) | ||||
| @@ -165,7 +165,7 @@ public class FunctionTemplate : MemberTemplate | ||||
|  | ||||
|         var arguments = args.Select(x => | ||||
|         { | ||||
|             var argType = RepresentationType.FromType(x.ParameterType); | ||||
|             var argType = TRU.FromType(x.ParameterType); | ||||
|  | ||||
|             if (argType == null) | ||||
|                 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; | ||||
|     } | ||||
|  | ||||
|     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,  | ||||
|         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) | ||||
|     { | ||||
|         this.Recordable = recordable; | ||||
| @@ -152,8 +152,8 @@ public class PropertyTemplate : MemberTemplate | ||||
|         var genericPropType = pi.PropertyType.IsGenericType ? pi.PropertyType.GetGenericTypeDefinition() : null; | ||||
|  | ||||
|         var propType = genericPropType == typeof(PropertyContext<>) ? | ||||
|                 RepresentationType.FromType(pi.PropertyType.GetGenericArguments()[0]) : | ||||
|                 RepresentationType.FromType(pi.PropertyType); | ||||
|                 TRU.FromType(pi.PropertyType.GetGenericArguments()[0]) : | ||||
|                 TRU.FromType(pi.PropertyType); | ||||
|  | ||||
|         if (propType == null) | ||||
|             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 valueType = RepresentationType.FromType(ci.FieldType); | ||||
|         var valueType = TRU.FromType(ci.FieldType); | ||||
|  | ||||
|         if (valueType == null) | ||||
|             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; | ||||
|  | ||||
|                 // return type | ||||
|                 var (rts, returnType) = RepresentationType.Parse(data, offset); | ||||
|                 var (rts, returnType) = TRU.Parse(data, offset); | ||||
|                 offset += rts; | ||||
|  | ||||
|                 // arguments count | ||||
| @@ -823,7 +823,7 @@ public class TypeTemplate | ||||
|  | ||||
|                 offset += (uint)data[offset] + 1; | ||||
|  | ||||
|                 var (dts, valueType) = RepresentationType.Parse(data, offset); | ||||
|                 var (dts, valueType) = TRU.Parse(data, offset); | ||||
|  | ||||
|                 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]); | ||||
|                 offset += (uint)data[offset] + 1; | ||||
|  | ||||
|                 var (dts, argType) = RepresentationType.Parse(data, offset); | ||||
|                 var (dts, argType) = TRU.Parse(data, offset); | ||||
|  | ||||
|                 offset += dts; | ||||
|  | ||||
| @@ -883,7 +883,7 @@ public class TypeTemplate | ||||
|                 var name = data.GetString(offset + 1, data[offset]); | ||||
|                 offset += (uint)data[offset] + 1; | ||||
|  | ||||
|                 var (dts, valueType) = RepresentationType.Parse(data, offset); | ||||
|                 var (dts, valueType) = TRU.Parse(data, offset); | ||||
|  | ||||
|                 offset += dts; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user