mirror of
				https://github.com/esiur/esiur-dotnet.git
				synced 2025-10-31 07:51:36 +00:00 
			
		
		
		
	2.2
This commit is contained in:
		
							
								
								
									
										372
									
								
								Esiur/Data/RepresentationType.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										372
									
								
								Esiur/Data/RepresentationType.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,372 @@ | ||||
| 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.Text; | ||||
|  | ||||
| namespace Esiur.Data | ||||
| { | ||||
|     public enum RepresentationTypeIdentifier | ||||
|     { | ||||
|         Void, | ||||
|         Dynamic, | ||||
|         Bool, | ||||
|         UInt8, | ||||
|         Int8, | ||||
|         Char, | ||||
|         Int16, | ||||
|         UInt16, | ||||
|         Int32, | ||||
|         UInt32, | ||||
|         Float32, | ||||
|         Int64, | ||||
|         UInt64, | ||||
|         Float64, | ||||
|         DateTime, | ||||
|         Int128, | ||||
|         UInt128, | ||||
|         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 | ||||
|     { | ||||
|         public Type? GetRuntimeType() | ||||
|         { | ||||
|             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), //Nullable ? typeof(Nullable<string>) : typeof(string), | ||||
|                 (RepresentationTypeIdentifier.DateTime) => Nullable ? typeof(DateTime?) : typeof(DateTime), | ||||
|                 (RepresentationTypeIdentifier.Resource) => typeof(IResource), | ||||
|                 (RepresentationTypeIdentifier.Record) => typeof(IRecord), | ||||
|                 (RepresentationTypeIdentifier.TypedRecord) => Warehouse.GetTemplateByClassId((Guid)GUID, TemplateType.Record).DefinedType, | ||||
|                 (RepresentationTypeIdentifier.TypedResource) => Warehouse.GetTemplateByClassId((Guid)GUID, TemplateType.Unspecified).DefinedType, | ||||
|                 (RepresentationTypeIdentifier.Enum) => Warehouse.GetTemplateByClassId((Guid)GUID, TemplateType.Enum).DefinedType, | ||||
|                 _ => null | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         public RepresentationTypeIdentifier Identifier; | ||||
|         public bool Nullable; | ||||
|         public Guid? GUID; | ||||
|         //public RepresentationType? SubType1; // List + Map | ||||
|         //public RepresentationType? SubType2; // Map | ||||
|         //public RepresentationType? SubType3; // No types yet | ||||
|  | ||||
|         public RepresentationType?[] SubTypes = new RepresentationType[3]; | ||||
|  | ||||
|         public static RepresentationType? FromType(Type type) | ||||
|         { | ||||
|             var nullType = System.Nullable.GetUnderlyingType(type); | ||||
|             var nullable = false; | ||||
|  | ||||
|             if (nullType != null) { | ||||
|                 type = nullType; | ||||
|                 nullable = true; | ||||
|             } | ||||
|  | ||||
|             if (type.IsGenericType) | ||||
|             { | ||||
|                 var genericType = type.GetGenericTypeDefinition(); | ||||
|                 if (genericType == typeof(List<>)) | ||||
|                 { | ||||
|                     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, subType); | ||||
|  | ||||
|                     } | ||||
|                 } | ||||
|                 else if (genericType == typeof(Map<,>)) | ||||
|                 { | ||||
|                     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, subType1, subType2); | ||||
|                     } | ||||
|                 } | ||||
|                 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++) | ||||
|                     { | ||||
|                         subTypes[i] = FromType(args[i]); | ||||
|                         if (subTypes[i] == null) | ||||
|                             return null; | ||||
|                     } | ||||
|  | ||||
|                     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++) | ||||
|                     { | ||||
|                         subTypes[i] = FromType(args[i]); | ||||
|                         if (subTypes[i] == null) | ||||
|                             return null; | ||||
|                     } | ||||
|  | ||||
|                     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++) | ||||
|                     { | ||||
|                         subTypes[i] = FromType(args[i]); | ||||
|                         if (subTypes[i] == null) | ||||
|                             return null; | ||||
|                     } | ||||
|  | ||||
|                     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++) | ||||
|                     { | ||||
|                         subTypes[i] = FromType(args[i]); | ||||
|                         if (subTypes[i] == null) | ||||
|                             return null; | ||||
|                     } | ||||
|  | ||||
|                     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++) | ||||
|                     { | ||||
|                         subTypes[i] = FromType(args[i]); | ||||
|                         if (subTypes[i] == null) | ||||
|                             return null; | ||||
|                     } | ||||
|  | ||||
|                     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++) | ||||
|                     { | ||||
|                         subTypes[i] = FromType(args[i]); | ||||
|                         if (subTypes[i] == null) | ||||
|                             return null; | ||||
|                     } | ||||
|  | ||||
|                     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, subType); | ||||
|  | ||||
|                 } | ||||
|             } | ||||
|             else 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>)) | ||||
|                 return new RepresentationType(RepresentationTypeIdentifier.Map, nullable); | ||||
|             else if (Codec.ImplementsInterface(type, typeof(IResource))) | ||||
|             { | ||||
|                 return new RepresentationType( | ||||
|                    RepresentationTypeIdentifier.TypedResource, | ||||
|                    nullable, | ||||
|                    TypeTemplate.GetTypeGuid(type) | ||||
|                 ); | ||||
|             } | ||||
|             else if (Codec.ImplementsInterface(type, typeof(IRecord))) | ||||
|             { | ||||
|                 return new RepresentationType( | ||||
|                    RepresentationTypeIdentifier.TypedRecord, | ||||
|                    nullable, | ||||
|                    TypeTemplate.GetTypeGuid(type) | ||||
|                 ); | ||||
|             } | ||||
|             else if (type.IsEnum) | ||||
|             { | ||||
|                 return new RepresentationType(RepresentationTypeIdentifier.Enum, nullable, TypeTemplate.GetTypeGuid(type)); | ||||
|             } | ||||
|             //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, Guid? guid = null, params RepresentationType[] subTypes) | ||||
|         { | ||||
|             Nullable = nullable; | ||||
|             Identifier = identifier; | ||||
|             GUID = guid; | ||||
|             SubTypes = subTypes; | ||||
|         } | ||||
|  | ||||
|         public byte[] Compose() | ||||
|         { | ||||
|             var rt = new BinaryList(); | ||||
|  | ||||
|             if (Nullable) | ||||
|                 rt.AddUInt8((byte)(0x80 | (byte)Identifier)); | ||||
|             else | ||||
|                 rt.AddUInt8((byte)Identifier); | ||||
|  | ||||
|             if (GUID != null) | ||||
|                 rt.AddUInt8Array(DC.ToBytes((Guid)GUID)); | ||||
|  | ||||
|             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 hasGUID = (header & 0x4) > 0; | ||||
|                 var subsCount = (header >> 3) & 0x7; | ||||
|  | ||||
|                 Guid? guid = null; | ||||
|  | ||||
|                 if (hasGUID) | ||||
|                 { | ||||
|                     guid = data.GetGuid(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, guid, subs)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return (1, new RepresentationType(identifier, nullable)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user