mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-06-27 13:33:13 +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