mirror of
				https://github.com/esiur/esiur-dotnet.git
				synced 2025-10-30 23:51:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1218 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			1218 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using Esiur.Core;
 | |
| using Esiur.Data;
 | |
| using Esiur.Data.GVWIE;
 | |
| using Esiur.Misc;
 | |
| using Esiur.Net.IIP;
 | |
| using Esiur.Resource;
 | |
| using Esiur.Resource.Template;
 | |
| using Microsoft.CodeAnalysis.CSharp.Syntax;
 | |
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.ComponentModel.DataAnnotations;
 | |
| using System.Linq;
 | |
| using System.Text;
 | |
| 
 | |
| namespace Esiur.Data;
 | |
| 
 | |
| public static class DataDeserializer
 | |
| {
 | |
|     public static object NullParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     public static object NullParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     public static object BooleanTrueParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     public static object BooleanTrueParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     public static object BooleanFalseParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     public static object BooleanFalseParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     public static object NotModifiedParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         return NotModified.Default;
 | |
|     }
 | |
| 
 | |
|     public static object NotModifiedParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return NotModified.Default;
 | |
|     }
 | |
| 
 | |
|     public static object UInt8ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         return tdu.Data[tdu.Offset];
 | |
|     }
 | |
|     public static object UInt8Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return tdu.Data[tdu.Offset];
 | |
|     }
 | |
| 
 | |
|     public static object Int8ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         return (sbyte)tdu.Data[tdu.Offset];
 | |
|     }
 | |
|     public static object Int8Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return (sbyte)tdu.Data[tdu.Offset];
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Char16ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(char*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Char16Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(char*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static object Char8ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         return (char)tdu.Data[tdu.Offset];
 | |
|     }
 | |
| 
 | |
|     public static object Char8Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return (char)tdu.Data[tdu.Offset];
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static unsafe object Int16ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(short*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Int16Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(short*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object UInt16ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(ushort*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object UInt16Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(ushort*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Int32ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(int*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Int32Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(int*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object UInt32ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(uint*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object UInt32Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(uint*)ptr;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static unsafe object Float32ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(float*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Float32Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(float*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Float64ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(double*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Float64Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(double*)ptr;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static unsafe object Decimal128ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(decimal*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Decimal128Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(decimal*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object UUIDParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         return new UUID(tdu.Data, tdu.Offset);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object UUIDParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return new UUID(tdu.Data, tdu.Offset);
 | |
|     }
 | |
| 
 | |
| 
 | |
| 
 | |
|     public static unsafe object Int128ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr1 = &tdu.Data[tdu.Offset])
 | |
|         fixed (byte* ptr2 = &tdu.Data[tdu.Offset + 8])
 | |
|             return new Int128(*(ulong*)ptr1, *(ulong*)ptr2);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Int128Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr1 = &tdu.Data[tdu.Offset])
 | |
|         fixed (byte* ptr2 = &tdu.Data[tdu.Offset + 8])
 | |
|             return new Int128(*(ulong*)ptr1, *(ulong*)ptr2);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object UInt128ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr1 = &tdu.Data[tdu.Offset])
 | |
|         fixed (byte* ptr2 = &tdu.Data[tdu.Offset + 8])
 | |
|             return new UInt128(*(ulong*)ptr1, *(ulong*)ptr2);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object UInt128Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr1 = &tdu.Data[tdu.Offset])
 | |
|         fixed (byte* ptr2 = &tdu.Data[tdu.Offset + 8])
 | |
|             return new UInt128(*(ulong*)ptr1, *(ulong*)ptr2);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Int64ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(long*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object Int64Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(long*)ptr;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static unsafe object UInt64ParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(ulong*)ptr;
 | |
|     }
 | |
| 
 | |
|     public static unsafe object UInt64Parser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return *(ulong*)ptr;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static unsafe object DateTimeParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return new DateTime(*(long*)ptr, DateTimeKind.Utc);
 | |
| 
 | |
|     }
 | |
|     public static unsafe object DateTimeParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return new DateTime(*(long*)ptr, DateTimeKind.Utc);
 | |
| 
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static unsafe object ResourceParser8Async(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         if (connection == null)
 | |
|             return new ResourceId(false, tdu.Data[tdu.Offset]);
 | |
|         else
 | |
|             return connection.Fetch(tdu.Data[tdu.Offset], requestSequence);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object ResourceParser8(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return new ResourceId(false, tdu.Data[tdu.Offset]);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object LocalResourceParser8Async(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         if (connection == null)
 | |
|             return new ResourceId(true, tdu.Data[tdu.Offset]);
 | |
|         else
 | |
|             return connection.Instance.Warehouse.GetById(tdu.Data[tdu.Offset]);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object LocalResourceParser8(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return new ResourceId(true, tdu.Data[tdu.Offset]);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object ResourceParser16Async(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             if (connection == null)
 | |
|                 return new ResourceId(false, *(ushort*)ptr);
 | |
|             else
 | |
|                 return connection.Fetch(*(ushort*)ptr, requestSequence);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object ResourceParser16(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return new ResourceId(false, *(ushort*)ptr);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static unsafe object LocalResourceParser16Async(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             if (connection == null)
 | |
|                 return new ResourceId(true, *(ushort*)ptr);
 | |
|             else
 | |
|                 return connection.Instance.Warehouse.GetById(*(ushort*)ptr);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object LocalResourceParser16(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return new ResourceId(true, *(ushort*)ptr);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object ResourceParser32Async(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             if (connection == null)
 | |
|                 return new ResourceId(false, *(uint*)ptr);
 | |
|             else
 | |
|                 return connection.Fetch(*(uint*)ptr, requestSequence);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object ResourceParser32(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return new ResourceId(false, *(uint*)ptr);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static unsafe object LocalResourceParser32Async(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             if (connection == null)
 | |
|                 return new ResourceId(true, *(uint*)ptr);
 | |
|             else
 | |
|                 return connection.Instance.Warehouse.GetById(*(uint*)ptr);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object LocalResourceParser32(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         fixed (byte* ptr = &tdu.Data[tdu.Offset])
 | |
|             return new ResourceId(true, *(uint*)ptr);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static unsafe object RawDataParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         return tdu.Data.Clip(tdu.Offset, (uint)tdu.ContentLength);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object RawDataParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return tdu.Data.Clip(tdu.Offset, (uint)tdu.ContentLength);
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static unsafe object StringParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         return tdu.Data.GetString(tdu.Offset, (uint)tdu.ContentLength);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object StringParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         return tdu.Data.GetString(tdu.Offset, (uint)tdu.ContentLength);
 | |
|     }
 | |
| 
 | |
|     public static unsafe object RecordParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
| 
 | |
|         var reply = new AsyncReply<IRecord>();
 | |
| 
 | |
|         var classId = tdu.Metadata.GetUUID(0);
 | |
| 
 | |
|         var template = connection.Instance.Warehouse.GetTemplateByClassId(classId, TemplateType.Record);
 | |
| 
 | |
|         var initRecord = (TypeTemplate template) =>
 | |
|         {
 | |
|             ListParserAsync(tdu, connection, requestSequence).Then(r =>
 | |
|             {
 | |
|                 var ar = (object[])r;
 | |
| 
 | |
|                 if (template == null)
 | |
|                 {
 | |
|                     // @TODO: add parse if no template settings
 | |
|                     reply.TriggerError(new AsyncException(ErrorType.Management, (ushort)ExceptionCode.TemplateNotFound,
 | |
|                             "Template not found for record."));
 | |
|                 }
 | |
|                 else if (template.DefinedType != null)
 | |
|                 {
 | |
|                     var record = Activator.CreateInstance(template.DefinedType) as IRecord;
 | |
|                     for (var i = 0; i < template.Properties.Length; i++)
 | |
|                     {
 | |
|                         try
 | |
|                         {
 | |
|                             //var v = Convert.ChangeType(ar[i], template.Properties[i].PropertyInfo.PropertyType);
 | |
|                             var v = DC.CastConvert(ar[i], template.Properties[i].PropertyInfo.PropertyType);
 | |
|                             template.Properties[i].PropertyInfo.SetValue(record, v);
 | |
|                         }
 | |
|                         catch (Exception ex)
 | |
|                         {
 | |
|                             Global.Log(ex);
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     reply.Trigger(record);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     var record = new Record();
 | |
| 
 | |
|                     for (var i = 0; i < template.Properties.Length; i++)
 | |
|                         record.Add(template.Properties[i].Name, ar[i]);
 | |
| 
 | |
|                     reply.Trigger(record);
 | |
|                 }
 | |
| 
 | |
|             });
 | |
|         };
 | |
| 
 | |
|         if (template != null)
 | |
|         {
 | |
|             initRecord(template);
 | |
|         }
 | |
|         else if (connection != null)
 | |
|         {
 | |
|             // try to get the template from the other end
 | |
|             connection.GetTemplate(classId).Then(tmp =>
 | |
|             {
 | |
|                 initRecord(tmp);
 | |
|             }).Error(x => reply.TriggerError(x));
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             initRecord(null);
 | |
|         }
 | |
| 
 | |
|         return reply;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static unsafe object RecordParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
| 
 | |
|         var classId = tdu.Metadata.GetUUID(0);
 | |
| 
 | |
| 
 | |
|         var template = warehouse.GetTemplateByClassId(classId, TemplateType.Record);
 | |
| 
 | |
|         var r = ListParser(tdu, warehouse);
 | |
| 
 | |
|         var ar = (object[])r;
 | |
| 
 | |
|         if (template == null)
 | |
|         {
 | |
|             // @TODO: add parse if no template settings
 | |
|             throw new AsyncException(ErrorType.Management, (ushort)ExceptionCode.TemplateNotFound,
 | |
|                     "Template not found for record.");
 | |
|         }
 | |
|         else if (template.DefinedType != null)
 | |
|         {
 | |
|             var record = Activator.CreateInstance(template.DefinedType) as IRecord;
 | |
|             for (var i = 0; i < template.Properties.Length; i++)
 | |
|             {
 | |
|                 try
 | |
|                 {
 | |
|                     //var v = Convert.ChangeType(ar[i], template.Properties[i].PropertyInfo.PropertyType);
 | |
|                     var v = DC.CastConvert(ar[i], template.Properties[i].PropertyInfo.PropertyType);
 | |
|                     template.Properties[i].PropertyInfo.SetValue(record, v);
 | |
|                 }
 | |
|                 catch (Exception ex)
 | |
|                 {
 | |
|                     Global.Log(ex);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return record;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             var record = new Record();
 | |
| 
 | |
|             for (var i = 0; i < template.Properties.Length; i++)
 | |
|                 record.Add(template.Properties[i].Name, ar[i]);
 | |
| 
 | |
|             return record;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public static unsafe object ConstantParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         throw new NotImplementedException();
 | |
|     }
 | |
| 
 | |
|     public static unsafe object ConstantParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         throw new NotImplementedException();
 | |
|     }
 | |
| 
 | |
|     public static unsafe AsyncReply EnumParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
| 
 | |
|         var classId = tdu.Metadata.GetUUID(0);
 | |
| 
 | |
| 
 | |
|         var index = tdu.Data[tdu.Offset];
 | |
| 
 | |
|         var template = connection.Instance.Warehouse.GetTemplateByClassId(classId, TemplateType.Enum);
 | |
| 
 | |
|         if (template != null)
 | |
|         {
 | |
|             return new AsyncReply(template.Constants[index].Value);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             var reply = new AsyncReply();
 | |
| 
 | |
|             connection.GetTemplate(classId).Then(tmp =>
 | |
|             {
 | |
|                 reply.Trigger(tmp.Constants[index].Value);
 | |
|             }).Error(x => reply.TriggerError(x));
 | |
| 
 | |
|             return reply;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public static unsafe object EnumParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
| 
 | |
|         var classId = tdu.Metadata.GetUUID(0);
 | |
| 
 | |
|         var index = tdu.Data[tdu.Offset];
 | |
| 
 | |
|         var template = warehouse.GetTemplateByClassId(classId, TemplateType.Enum);
 | |
| 
 | |
|         if (template != null)
 | |
|         {
 | |
|             return template.Constants[index].Value;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             throw new AsyncException(ErrorType.Management, (ushort)ExceptionCode.TemplateNotFound,
 | |
|                     "Template not found for enum.");
 | |
|         }
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static AsyncReply RecordListParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         var rt = new AsyncBag<IRecord>();
 | |
| 
 | |
|         var length = tdu.ContentLength;
 | |
|         var offset = tdu.Offset;
 | |
| 
 | |
|         while (length > 0)
 | |
|         {
 | |
|             var (cs, reply) = Codec.ParseAsync(tdu.Data, offset, connection, requestSequence);
 | |
| 
 | |
|             rt.Add(reply);
 | |
| 
 | |
|             if (cs > 0)
 | |
|             {
 | |
|                 offset += (uint)cs;
 | |
|                 length -= (uint)cs;
 | |
|             }
 | |
|             else
 | |
|                 throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|         }
 | |
| 
 | |
|         rt.Seal();
 | |
|         return rt;
 | |
|     }
 | |
| 
 | |
|     public static object RecordListParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         var rt = new List<IRecord>();
 | |
| 
 | |
|         var length = tdu.ContentLength;
 | |
|         var offset = tdu.Offset;
 | |
| 
 | |
|         while (length > 0)
 | |
|         {
 | |
|             var (cs, reply) = Codec.ParseSync(tdu.Data, offset, warehouse);
 | |
| 
 | |
|             rt.Add(reply as IRecord);
 | |
| 
 | |
|             if (cs > 0)
 | |
|             {
 | |
|                 offset += (uint)cs;
 | |
|                 length -= (uint)cs;
 | |
|             }
 | |
|             else
 | |
|                 throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|         }
 | |
| 
 | |
|         return rt.ToArray();
 | |
|     }
 | |
| 
 | |
|     public static AsyncReply ResourceListParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         var rt = new AsyncBag<IResource>();
 | |
| 
 | |
|         var length = tdu.ContentLength;
 | |
|         var offset = tdu.Offset;
 | |
| 
 | |
|         while (length > 0)
 | |
|         {
 | |
|             var (cs, reply) = Codec.ParseAsync(tdu.Data, offset, connection, requestSequence);
 | |
| 
 | |
|             rt.Add(reply);
 | |
| 
 | |
|             if (cs > 0)
 | |
|             {
 | |
|                 offset += (uint)cs;
 | |
|                 length -= (uint)cs;
 | |
|             }
 | |
|             else
 | |
|                 throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|         }
 | |
| 
 | |
|         rt.Seal();
 | |
|         return rt;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static object ResourceListParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         var rt = new List<IResource>();
 | |
| 
 | |
|         var length = tdu.ContentLength;
 | |
|         var offset = tdu.Offset;
 | |
| 
 | |
|         while (length > 0)
 | |
|         {
 | |
|             var (cs, reply) = Codec.ParseSync(tdu.Data, offset, warehouse);
 | |
| 
 | |
|             rt.Add(reply as IResource);
 | |
| 
 | |
|             if (cs > 0)
 | |
|             {
 | |
|                 offset += (uint)cs;
 | |
|                 length -= (uint)cs;
 | |
|             }
 | |
|             else
 | |
|                 throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|         }
 | |
| 
 | |
|         return rt.ToArray();
 | |
|     }
 | |
| 
 | |
|     public static AsyncBag<object> ListParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         var rt = new AsyncBag<object>();
 | |
| 
 | |
| 
 | |
|         var offset = tdu.Offset;
 | |
|         var length = tdu.ContentLength;
 | |
| 
 | |
|         while (length > 0)
 | |
|         {
 | |
|             var (cs, reply) = Codec.ParseAsync(tdu.Data, offset, connection, requestSequence);
 | |
| 
 | |
|             rt.Add(reply);
 | |
| 
 | |
|             if (cs > 0)
 | |
|             {
 | |
|                 offset += (uint)cs;
 | |
|                 length -= (uint)cs;
 | |
|             }
 | |
|             else
 | |
|                 throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|         }
 | |
| 
 | |
|         rt.Seal();
 | |
|         return rt;
 | |
|     }
 | |
| 
 | |
|     public static object ListParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         var rt = new List<object>();
 | |
| 
 | |
|         var offset = tdu.Offset;
 | |
|         var length = tdu.ContentLength;
 | |
| 
 | |
|         while (length > 0)
 | |
|         {
 | |
|             var (cs, reply) = Codec.ParseSync(tdu.Data, offset, warehouse);
 | |
| 
 | |
|             rt.Add(reply);
 | |
| 
 | |
|             if (cs > 0)
 | |
|             {
 | |
|                 offset += (uint)cs;
 | |
|                 length -= (uint)cs;
 | |
|             }
 | |
|             else
 | |
|                 throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|         }
 | |
| 
 | |
|         return rt.ToArray();
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static (uint, ulong, object[]) LimitedCountListParser(byte[] data, uint offset, ulong length, Warehouse warehouse, uint countLimit = uint.MaxValue)
 | |
|     {
 | |
|         var rt = new List<object>();
 | |
| 
 | |
|         while (length > 0 && rt.Count < countLimit)
 | |
|         {
 | |
|             var (cs, reply) = Codec.ParseSync(data, offset, warehouse);
 | |
| 
 | |
|             rt.Add(reply);
 | |
| 
 | |
|             if (cs > 0)
 | |
|             {
 | |
|                 offset += (uint)cs;
 | |
|                 length -= (uint)cs;
 | |
|             }
 | |
|             else
 | |
|                 throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|         }
 | |
| 
 | |
|         return (offset, length, rt.ToArray());
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static AsyncReply TypedMapParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         // get key type
 | |
| 
 | |
|         var (keyCs, keyRepType) = TRU.Parse(tdu.Metadata, 0);
 | |
|         var (valueCs, valueRepType) = TRU.Parse(tdu.Metadata, keyCs);
 | |
| 
 | |
|         var wh = connection.Instance.Warehouse;
 | |
| 
 | |
|         var map = (IMap)Activator.CreateInstance(typeof(Map<,>).MakeGenericType(keyRepType.GetRuntimeType(wh), valueRepType.GetRuntimeType(wh)));
 | |
| 
 | |
|         var rt = new AsyncReply();
 | |
| 
 | |
|         var results = new AsyncBag<object>();
 | |
| 
 | |
|         var offset = tdu.Offset;
 | |
|         var length = tdu.ContentLength;
 | |
| 
 | |
|         while (length > 0)
 | |
|         {
 | |
|             var (cs, reply) = Codec.ParseAsync(tdu.Data, offset, connection, requestSequence);
 | |
| 
 | |
| 
 | |
|             results.Add(reply);
 | |
| 
 | |
|             if (cs > 0)
 | |
|             {
 | |
|                 offset += (uint)cs;
 | |
|                 length -= (uint)cs;
 | |
|             }
 | |
|             else
 | |
|                 throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|         }
 | |
| 
 | |
|         results.Seal();
 | |
| 
 | |
|         results.Then(ar =>
 | |
|         {
 | |
|             for (var i = 0; i < ar.Length; i += 2)
 | |
|                 map.Add(ar[i], ar[i + 1]);
 | |
| 
 | |
|             rt.Trigger(map);
 | |
|         });
 | |
| 
 | |
| 
 | |
|         return rt;
 | |
| 
 | |
|     }
 | |
| 
 | |
|     public static object TypedMapParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         // get key type
 | |
| 
 | |
|         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)));
 | |
| 
 | |
| 
 | |
|         var results = new List<object>();
 | |
| 
 | |
|         var offset = tdu.Offset;
 | |
|         var length = tdu.ContentLength;
 | |
| 
 | |
|         while (length > 0)
 | |
|         {
 | |
|             var (cs, reply) = Codec.ParseSync(tdu.Data, offset, warehouse);
 | |
| 
 | |
| 
 | |
|             results.Add(reply);
 | |
| 
 | |
|             if (cs > 0)
 | |
|             {
 | |
|                 offset += (uint)cs;
 | |
|                 length -= (uint)cs;
 | |
|             }
 | |
|             else
 | |
|                 throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|         }
 | |
| 
 | |
|         for (var i = 0; i < results.Count; i += 2)
 | |
|             map.Add(results[i], results[i + 1]);
 | |
| 
 | |
|         return map;
 | |
|     }
 | |
| 
 | |
|     public static AsyncReply TupleParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         var rt = new AsyncReply();
 | |
| 
 | |
|         var results = new AsyncBag<object>();
 | |
|         var tupleSize = tdu.Metadata[0];
 | |
| 
 | |
|         var types = new List<Type>();
 | |
| 
 | |
|         uint mtOffset = 1;
 | |
|         for (var i = 0; i < tupleSize; i++)
 | |
|         {
 | |
|             var (cs, rep) = TRU.Parse(tdu.Metadata, mtOffset);
 | |
|             types.Add(rep.GetRuntimeType(connection.Instance.Warehouse));
 | |
|             mtOffset += cs;
 | |
|         }
 | |
| 
 | |
|         var length = tdu.ContentLength;
 | |
|         var offset = tdu.Offset;
 | |
| 
 | |
| 
 | |
|         while (length > 0)
 | |
|         {
 | |
|             var (cs, reply) = Codec.ParseAsync(tdu.Data, offset, connection, requestSequence);
 | |
| 
 | |
|             results.Add(reply);
 | |
| 
 | |
|             if (cs > 0)
 | |
|             {
 | |
|                 offset += (uint)cs;
 | |
|                 length -= (uint)cs;
 | |
|             }
 | |
|             else
 | |
|                 throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|         }
 | |
| 
 | |
|         results.Seal();
 | |
| 
 | |
| 
 | |
|         results.Then(ar =>
 | |
|                 {
 | |
|                     if (ar.Length == 2)
 | |
|                     {
 | |
|                         var type = typeof(ValueTuple<,>).MakeGenericType(types.ToArray());
 | |
|                         rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1]));
 | |
|                     }
 | |
|                     else if (ar.Length == 3)
 | |
|                     {
 | |
|                         var type = typeof(ValueTuple<,,>).MakeGenericType(types.ToArray());
 | |
|                         rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2]));
 | |
|                     }
 | |
|                     else if (ar.Length == 4)
 | |
|                     {
 | |
|                         var type = typeof(ValueTuple<,,,>).MakeGenericType(types.ToArray());
 | |
|                         rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2], ar[3]));
 | |
|                     }
 | |
|                     else if (ar.Length == 5)
 | |
|                     {
 | |
|                         var type = typeof(ValueTuple<,,,,>).MakeGenericType(types.ToArray());
 | |
|                         rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2], ar[3], ar[4]));
 | |
|                     }
 | |
|                     else if (ar.Length == 6)
 | |
|                     {
 | |
|                         var type = typeof(ValueTuple<,,,,,>).MakeGenericType(types.ToArray());
 | |
|                         rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2], ar[3], ar[4], ar[5]));
 | |
|                     }
 | |
|                     else if (ar.Length == 7)
 | |
|                     {
 | |
|                         var type = typeof(ValueTuple<,,,,,,>).MakeGenericType(types.ToArray());
 | |
|                         rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2], ar[3], ar[4], ar[5], ar[6]));
 | |
|                     }
 | |
|                 });
 | |
| 
 | |
|         return rt;
 | |
|     }
 | |
| 
 | |
|     public static object TupleParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         var results = new List<object>();
 | |
|         var tupleSize = tdu.Metadata[0];
 | |
| 
 | |
|         var types = new List<Type>();
 | |
| 
 | |
|         uint mtOffset = 1;
 | |
|         for (var i = 0; i < tupleSize; i++)
 | |
|         {
 | |
|             var (cs, rep) = TRU.Parse(tdu.Metadata, mtOffset);
 | |
|             types.Add(rep.GetRuntimeType(warehouse));
 | |
|             mtOffset += cs;
 | |
|         }
 | |
| 
 | |
|         var length = tdu.ContentLength;
 | |
|         var offset = tdu.Offset;
 | |
| 
 | |
|         while (length > 0)
 | |
|         {
 | |
|             var (cs, reply) = Codec.ParseSync(tdu.Data, offset, warehouse);
 | |
| 
 | |
|             results.Add(reply);
 | |
| 
 | |
|             if (cs > 0)
 | |
|             {
 | |
|                 offset += (uint)cs;
 | |
|                 length -= (uint)cs;
 | |
|             }
 | |
|             else
 | |
|                 throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|         }
 | |
| 
 | |
| 
 | |
|         if (results.Count == 2)
 | |
|         {
 | |
|             var type = typeof(ValueTuple<,>).MakeGenericType(types.ToArray());
 | |
|             return Activator.CreateInstance(type, results[0], results[1]);
 | |
|         }
 | |
|         else if (results.Count == 3)
 | |
|         {
 | |
|             var type = typeof(ValueTuple<,,>).MakeGenericType(types.ToArray());
 | |
|             return Activator.CreateInstance(type, results[0], results[1], results[2]);
 | |
|         }
 | |
|         else if (results.Count == 4)
 | |
|         {
 | |
|             var type = typeof(ValueTuple<,,,>).MakeGenericType(types.ToArray());
 | |
|             return Activator.CreateInstance(type, results[0], results[1], results[2], results[3]);
 | |
|         }
 | |
|         else if (results.Count == 5)
 | |
|         {
 | |
|             var type = typeof(ValueTuple<,,,,>).MakeGenericType(types.ToArray());
 | |
|             return Activator.CreateInstance(type, results[0], results[1], results[2], results[3], results[4]);
 | |
|         }
 | |
|         else if (results.Count == 6)
 | |
|         {
 | |
|             var type = typeof(ValueTuple<,,,,,>).MakeGenericType(types.ToArray());
 | |
|             return Activator.CreateInstance(type, results[0], results[1], results[2], results[3], results[4], results[5]);
 | |
|         }
 | |
|         else if (results.Count == 7)
 | |
|         {
 | |
|             var type = typeof(ValueTuple<,,,,,,>).MakeGenericType(types.ToArray());
 | |
|             return Activator.CreateInstance(type, results[0], results[1], results[2], results[3], results[4], results[5], results[6]);
 | |
|         }
 | |
| 
 | |
|         throw new Exception("Unknown tuple length.");
 | |
| 
 | |
|     }
 | |
| 
 | |
|     public static AsyncReply TypedListParserAsync(ParsedTDU tdu, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         // get the type
 | |
|         var (hdrCs, rep) = TRU.Parse(tdu.Metadata, 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:
 | |
| 
 | |
|                 var rt = new AsyncBag<object>();
 | |
| 
 | |
|                 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;
 | |
|                     }
 | |
| 
 | |
|                     var (cs, reply) = Codec.ParseAsync(tdu.Data, offset, connection, requestSequence);
 | |
| 
 | |
|                     rt.Add(reply);
 | |
| 
 | |
|                     if (cs > 0)
 | |
|                     {
 | |
|                         offset += (uint)cs;
 | |
|                         length -= (uint)cs;
 | |
|                     }
 | |
|                     else
 | |
|                         throw new Exception("Error while parsing structured data");
 | |
| 
 | |
|                 }
 | |
| 
 | |
|                 rt.Seal();
 | |
|                 return rt;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public static object TypedListParser(ParsedTDU tdu, Warehouse warehouse)
 | |
|     {
 | |
|         // get the type
 | |
|         var (hdrCs, rep) = TRU.Parse(tdu.Metadata, 0);
 | |
| 
 | |
|         switch (rep.Identifier)
 | |
|         {
 | |
|             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:
 | |
| 
 | |
| 
 | |
|                 var list = new List<object>();
 | |
| 
 | |
|                 ParsedTDU current;
 | |
|                 ParsedTDU? previous = null;
 | |
| 
 | |
|                 var offset = tdu.Offset;
 | |
|                 var length = tdu.ContentLength;
 | |
|                 var ends = offset + (uint)length;
 | |
| 
 | |
|                 while (length > 0)
 | |
|                 {
 | |
|                     current = ParsedTDU.Parse(tdu.Data, offset, ends);
 | |
| 
 | |
|                     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;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public static AsyncBag<PropertyValue> PropertyValueArrayParserAsync(byte[] data, uint offset, uint length, DistributedConnection connection, uint[] requestSequence)//, bool ageIncluded = true)
 | |
|     {
 | |
|         var rt = new AsyncBag<PropertyValue>();
 | |
| 
 | |
| 
 | |
|         ListParserAsync(new ParsedTDU() { Data = data, Offset = offset, ContentLength = length }
 | |
|                         , connection, requestSequence).Then(x =>
 | |
|         {
 | |
|             var ar = (object[])x;
 | |
|             var pvs = new List<PropertyValue>();
 | |
| 
 | |
|             for (var i = 0; i < ar.Length; i += 3)
 | |
|                 pvs.Add(new PropertyValue(ar[2], (ulong?)ar[0], (DateTime?)ar[1]));
 | |
| 
 | |
| 
 | |
|             rt.Trigger(pvs.ToArray());
 | |
|         });
 | |
| 
 | |
|         return rt;
 | |
| 
 | |
|     }
 | |
| 
 | |
| 
 | |
|     public static (uint, AsyncReply<PropertyValue>) PropertyValueParserAsync(byte[] data, uint offset, DistributedConnection connection, uint[] requestSequence)//, bool ageIncluded = true)
 | |
|     {
 | |
|         var reply = new AsyncReply<PropertyValue>();
 | |
| 
 | |
|         var age = data.GetUInt64(offset, Endian.Little);
 | |
|         offset += 8;
 | |
| 
 | |
|         DateTime date = data.GetDateTime(offset, Endian.Little);
 | |
|         offset += 8;
 | |
| 
 | |
| 
 | |
|         var (valueSize, results) = Codec.ParseAsync(data, offset, connection, requestSequence);
 | |
| 
 | |
|         if (results is AsyncReply)
 | |
|         {
 | |
|             (results as AsyncReply).Then(value =>
 | |
|             {
 | |
|                 reply.Trigger(new PropertyValue(value, age, date));
 | |
|             });
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             reply.Trigger(new PropertyValue(results, age, date));
 | |
|         }
 | |
| 
 | |
|         return (16 + valueSize, reply);
 | |
|     }
 | |
| 
 | |
|     public static AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> HistoryParserAsync(byte[] data, uint offset, uint length, IResource resource, DistributedConnection connection, uint[] requestSequence)
 | |
|     {
 | |
|         //var count = (int)toAge - (int)fromAge;
 | |
| 
 | |
|         var list = new KeyList<PropertyTemplate, PropertyValue[]>();
 | |
| 
 | |
|         var reply = new AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>>();
 | |
| 
 | |
|         var bagOfBags = new AsyncBag<PropertyValue[]>();
 | |
| 
 | |
|         var ends = offset + length;
 | |
|         while (offset < ends)
 | |
|         {
 | |
|             var index = data[offset++];
 | |
|             var pt = resource.Instance.Template.GetPropertyTemplateByIndex(index);
 | |
|             list.Add(pt, null);
 | |
|             var cs = data.GetUInt32(offset, Endian.Little);
 | |
|             offset += 4;
 | |
| 
 | |
|             var (len, pv) = PropertyValueParserAsync(data, offset, connection, requestSequence);
 | |
| 
 | |
|             bagOfBags.Add(pv);// ParsePropertyValueArray(data, offset, cs, connection));
 | |
|             offset += len;
 | |
|         }
 | |
| 
 | |
|         bagOfBags.Seal();
 | |
| 
 | |
|         bagOfBags.Then(x =>
 | |
|         {
 | |
|             for (var i = 0; i < list.Count; i++)
 | |
|                 list[list.Keys.ElementAt(i)] = x[i];
 | |
| 
 | |
|             reply.Trigger(list);
 | |
|         });
 | |
| 
 | |
|         return reply;
 | |
| 
 | |
|     }
 | |
| 
 | |
| }
 |