2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-06-27 05:23:13 +00:00
This commit is contained in:
2022-03-09 21:55:30 +03:00
parent 530df018ec
commit 9a174f406f
106 changed files with 5166 additions and 4398 deletions

View File

@ -47,170 +47,7 @@ public class BinaryList
}
/*
/// <summary>
/// Converts parameters to binary in same order
/// </summary>
/// <param name="values">Variables to convert</param>
public static byte[] ToBytes(params object[] values)
{
var list = new List<byte>();
foreach (var i in values)
{
if (i is byte)
list.Add((byte)i);
else
{
#if NETSTANDARD
MethodInfo mi = typeof(DC).GetTypeInfo().GetMethod("ToBytes", new Type[] { i.GetType() });
#else
MethodInfo mi = typeof(DC).GetMethod("ToBytes", new Type[] { i.GetType() });
#endif
if (mi != null)
{
var b = (byte[])mi.Invoke(null, new object[] { i });
list.AddRange(b);
}
}
}
return list.ToArray();
}
/// <summary>
/// Create a new instance of BinaryList
/// </summary>
/// <param name="values">Populate the list items</param>
public BinaryList(params object[] values)
{
AddRange(values);
}
/// <summary>
/// Add an array of items at the end of the list
/// </summary>
/// <param name="values">Array of items</param>
public void AddRange(object[] values)
{
foreach (var i in values)
{
if (i is byte)
list.Add((byte)i);
else
{
#if NETSTANDARD
MethodInfo mi = typeof(DC).GetTypeInfo().GetMethod("ToBytes", new Type[] { i.GetType() });
#else
MethodInfo mi = typeof(DC).GetMethod("ToBytes", new Type[] { i.GetType() });
#endif
if (mi != null)
{
var b = (byte[])mi.Invoke(null, new object[] {i});
list.AddRange(b);
}
}
}
}
/// <summary>
/// Add multiple items at the end of the list
/// </summary>
/// <param name="values">Parameters of items</param>
public void Append(params object[] values)
{
AddRange(values);
}
/// <summary>
/// Insert new items to the list at a specified index
/// </summary>
/// <param name="offset">Position in the list</param>
/// <param name="values">Items to insert</param>
public void Insert(int offset, params object[] values)
{
foreach (var i in values)
{
if (i is byte)
{
list.Insert(offset++, (byte)i);
}
else
{
#if NETSTANDARD
MethodInfo mi = typeof(DC).GetTypeInfo().GetMethod("ToBytes", new Type[] { i.GetType() });
#else
MethodInfo mi = typeof(DC).GetMethod("ToBytes", new Type[] { i.GetType() });
#endif
if (mi != null)
{
var b = (byte[])mi.Invoke(null, new object[] { i });
list.InsertRange(offset, b);
offset += b.Length;
}
}
}
}
/// <summary>
/// Number of the items in the list
/// </summary>
public int Length
{
get
{
return list.Count;
}
}
/*
public void Append(byte data)
{
list.Add(data);
}
public void Append(byte[] data)
{
list.AddRange(data);
}
public void Append(int data)
{
list.AddRange(DC.ToBytes(data));
}
public void Append(uint data)
{
list.AddRange(DC.ToBytes(data));
}
public void Append(float data)
{
list.AddRange(DC.ToBytes(data));
}
public void Append(short data)
{
list.AddRange(DC.ToBytes(data));
}
public void Append(ushort data)
{
list.AddRange(DC.ToBytes(data));
}
public void Append(double data)
{
list.AddRange(DC.ToBytes(data));
}
public void Append(sbyte data)
{
list.Add((byte)data);
}
*/
public Endian Endian { get; set; } = Endian.Little;
public int Length => list.Count;
@ -227,18 +64,6 @@ public class BinaryList
}
public BinaryList AddDateTimeArray(DateTime[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertDateTimeArray(int position, DateTime[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddGuid(Guid value)
{
list.AddRange(DC.ToBytes(value));
@ -251,18 +76,7 @@ public class BinaryList
return this;
}
public BinaryList AddGuidArray(Guid[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertGuidArray(int position, Guid[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddUInt8Array(byte[] value)
{
@ -302,18 +116,7 @@ public class BinaryList
return this;
}
public BinaryList AddStringArray(string[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertStringArray(int position, string[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList InsertUInt8(int position, byte value)
{
list.Insert(position, value);
@ -338,17 +141,7 @@ public class BinaryList
return this;
}
public BinaryList AddInt8Array(sbyte[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertInt8Array(int position, sbyte[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddChar(char value)
@ -363,20 +156,7 @@ public class BinaryList
return this;
}
public BinaryList AddCharArray(char[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertCharArray(int position, char[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddBoolean(bool value)
public BinaryList AddBoolean(bool value)
{
list.AddRange(DC.ToBytes(value));
return this;
@ -388,314 +168,106 @@ public class BinaryList
return this;
}
public BinaryList AddBooleanArray(bool[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertBooleanArray(int position, bool[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddUInt16(ushort value)
{
list.AddRange(DC.ToBytes(value));
list.AddRange(DC.ToBytes(value, Endian));
return this;
}
public BinaryList InsertUInt16(int position, ushort value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddUInt16Array(ushort[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertUInt16Array(int position, ushort[] value)
{
list.InsertRange(position, DC.ToBytes(value));
list.InsertRange(position, DC.ToBytes(value, Endian));
return this;
}
public BinaryList AddInt16(short value)
{
list.AddRange(DC.ToBytes(value));
list.AddRange(DC.ToBytes(value, Endian));
return this;
}
public BinaryList InsertInt16(int position, short value)
{
list.InsertRange(position, DC.ToBytes(value));
list.InsertRange(position, DC.ToBytes(value, Endian));
return this;
}
public BinaryList AddInt16Array(short[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertInt16Array(int position, short[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddUInt32(uint value)
{
list.AddRange(DC.ToBytes(value));
list.AddRange(DC.ToBytes(value, Endian));
return this;
}
public BinaryList InsertUInt32(int position, uint value)
{
list.InsertRange(position, DC.ToBytes(value));
list.InsertRange(position, DC.ToBytes(value, Endian));
return this;
}
public BinaryList AddUInt32Array(uint[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertUInt32Array(int position, uint[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddInt32(int value)
{
list.AddRange(DC.ToBytes(value));
list.AddRange(DC.ToBytes(value, Endian));
return this;
}
public BinaryList InsertInt32(int position, int value)
{
list.InsertRange(position, DC.ToBytes(value));
list.InsertRange(position, DC.ToBytes(value, Endian));
return this;
}
public BinaryList AddInt32Array(int[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertInt32Array(int position, int[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddUInt64(ulong value)
{
list.AddRange(DC.ToBytes(value));
list.AddRange(DC.ToBytes(value, Endian));
return this;
}
public BinaryList InsertUInt64(int position, ulong value)
{
list.InsertRange(position, DC.ToBytes(value));
list.InsertRange(position, DC.ToBytes(value, Endian));
return this;
}
public BinaryList AddUInt64Array(ulong[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertUInt64Array(int position, ulong[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddInt64(long value)
{
list.AddRange(DC.ToBytes(value));
list.AddRange(DC.ToBytes(value, Endian));
return this;
}
public BinaryList InsertInt64(int position, long value)
{
list.InsertRange(position, DC.ToBytes(value));
list.InsertRange(position, DC.ToBytes(value, Endian));
return this;
}
public BinaryList AddInt64Array(long[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertInt64Array(int position, long[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddFloat32(float value)
{
list.AddRange(DC.ToBytes(value));
list.AddRange(value.ToBytes(Endian));
return this;
}
public BinaryList InsertFloat32(int position, float value)
{
list.InsertRange(position, DC.ToBytes(value));
list.InsertRange(position, value.ToBytes(Endian));
return this;
}
public BinaryList AddFloat32Array(float[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertFloat32Array(int position, float[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList AddFloat64(double value)
{
list.AddRange(DC.ToBytes(value));
list.AddRange(value.ToBytes(Endian));
return this;
}
public BinaryList InsertFloat64(int position, double value)
{
list.InsertRange(position, DC.ToBytes(value));
list.InsertRange(position, value.ToBytes(Endian));
return this;
}
public BinaryList AddFloat64Array(double[] value)
{
list.AddRange(DC.ToBytes(value));
return this;
}
public BinaryList InsertFloat64Array(int position, double[] value)
{
list.InsertRange(position, DC.ToBytes(value));
return this;
}
public BinaryList Add(DataType type, object value)
{
switch (type)
{
case DataType.Bool:
AddBoolean((bool)value);
return this;
case DataType.BoolArray:
AddBooleanArray((bool[])value);
return this;
case DataType.UInt8:
AddUInt8((byte)value);
return this;
case DataType.UInt8Array:
AddUInt8Array((byte[])value);
return this;
case DataType.Int8:
AddInt8((sbyte)value);
return this;
case DataType.Int8Array:
AddInt8Array((sbyte[])value);
return this;
case DataType.Char:
AddChar((char)value);
return this;
case DataType.CharArray:
AddCharArray((char[])value);
return this;
case DataType.UInt16:
AddUInt16((ushort)value);
return this;
case DataType.UInt16Array:
AddUInt16Array((ushort[])value);
return this;
case DataType.Int16:
AddInt16((short)value);
return this;
case DataType.Int16Array:
AddInt16Array((short[])value);
return this;
case DataType.UInt32:
AddUInt32((uint)value);
return this;
case DataType.UInt32Array:
AddUInt32Array((uint[])value);
return this;
case DataType.Int32:
AddInt32((int)value);
return this;
case DataType.Int32Array:
AddInt32Array((int[])value);
return this;
case DataType.UInt64:
AddUInt64((ulong)value);
return this;
case DataType.UInt64Array:
AddUInt64Array((ulong[])value);
return this;
case DataType.Int64:
AddInt64((long)value);
return this;
case DataType.Int64Array:
AddInt64Array((long[])value);
return this;
case DataType.Float32:
AddFloat32((float)value);
return this;
case DataType.Float32Array:
AddFloat32Array((float[])value);
return this;
case DataType.Float64:
AddFloat64((double)value);
return this;
case DataType.Float64Array:
AddFloat64Array((double[])value);
return this;
case DataType.String:
AddString((string)value);
return this;
case DataType.StringArray:
AddStringArray((string[])value);
return this;
case DataType.DateTime:
AddDateTime((DateTime)value);
return this;
case DataType.DateTimeArray:
AddDateTimeArray((DateTime[])value);
return this;
default:
throw new Exception("Not Implemented " + type.ToString());
//return this;
}
}
/// <summary>
/// Convert the list to an array of bytes
/// </summary>
@ -708,6 +280,5 @@ public class BinaryList
public virtual AsyncReply<object[]> Done()
{
return null;
//
}
}

File diff suppressed because it is too large Load Diff

View File

@ -93,10 +93,10 @@ public static class DC // Data Converter
rt.Set(value);
return rt;
}
else if (sourceType == typeof(Structure) && sourceType.IsAssignableFrom(destinationType))
{
return Structure.FromStructure((Structure)value, destinationType);
}
//else if (sourceType == typeof(Structure) && sourceType.IsAssignableFrom(destinationType))
//{
// return Structure.FromStructure((Structure)value, destinationType);
//}
else if (destinationType.IsEnum)
{
return Enum.ToObject(destinationType, value);
@ -190,45 +190,6 @@ public static class DC // Data Converter
return value.ToByteArray();
}
public static byte[] ToBytes(Guid[] value)
{
var rt = new List<byte>();
foreach (var g in value)
rt.AddRange(g.ToByteArray());
return rt.ToArray();
}
public static byte[] ToBytes(char[] value)
{
List<byte> rt = new List<byte>();
for (int i = 0; i < value.Length; i++)
rt.AddRange(ToBytes(value[i]));
return rt.ToArray();
}
public static byte[] ToBytes(short[] value)
{
List<byte> rt = new List<byte>();
for (int i = 0; i < value.Length; i++)
rt.AddRange(ToBytes(value[i]));
return rt.ToArray();
}
public static byte[] ToBytes(ushort[] value)
{
List<byte> rt = new List<byte>();
for (int i = 0; i < value.Length; i++)
rt.AddRange(ToBytes(value[i]));
return rt.ToArray();
}
public static void Append(ref byte[] dst, byte[] src)
{
@ -265,88 +226,6 @@ public static class DC // Data Converter
}
public static byte[] ToBytes(this int[] value)
{
List<byte> rt = new List<byte>();
for (int i = 0; i < value.Length; i++)
rt.AddRange(ToBytes(value[i]));
return rt.ToArray();
}
public static byte[] ToBytes(this uint[] value)
{
List<byte> rt = new List<byte>();
for (int i = 0; i < value.Length; i++)
rt.AddRange(ToBytes(value[i]));
return rt.ToArray();
}
public static byte[] ToBytes(this long[] value)
{
List<byte> rt = new List<byte>();
for (int i = 0; i < value.Length; i++)
rt.AddRange(ToBytes(value[i]));
return rt.ToArray();
}
public static byte[] ToBytes(this ulong[] value)
{
List<byte> rt = new List<byte>();
for (int i = 0; i < value.Length; i++)
rt.AddRange(ToBytes(value[i]));
return rt.ToArray();
}
public static byte[] ToBytes(this float[] value)
{
List<byte> rt = new List<byte>();
for (int i = 0; i < value.Length; i++)
rt.AddRange(ToBytes(value[i]));
return rt.ToArray();
}
public static byte[] ToBytes(this double[] value)
{
List<byte> rt = new List<byte>();
for (int i = 0; i < value.Length; i++)
rt.AddRange(ToBytes(value[i]));
return rt.ToArray();
}
public static byte[] ToBytes(this decimal[] value)
{
List<byte> rt = new List<byte>();
for (int i = 0; i < value.Length; i++)
rt.AddRange(ToBytes(value[i]));
return rt.ToArray();
}
public static byte[] ToBytes(this DateTime[] value)
{
List<byte> rt = new List<byte>();
for (int i = 0; i < value.Length; i++)
rt.AddRange(ToBytes(value[i]));
return rt.ToArray();
}
public static byte[] ToBytes(this string[] value)
{
@ -356,7 +235,7 @@ public static class DC // Data Converter
{
byte[] ba = ToBytes(value[i]);
// add string length
rt.AddRange(ToBytes(ba.Length));
rt.AddRange(ToBytes(ba.Length, Endian.Little));
// add encoded string
rt.AddRange(ba);
}
@ -364,41 +243,68 @@ public static class DC // Data Converter
return rt.ToArray();
}
public static unsafe byte[] ToBytes(this int value)
public static unsafe byte[] ToBytes(this int value, Endian endian)
{
var rt = new byte[4];
byte* p = (byte*)&value;
rt[0] = *(p + 3);
rt[1] = *(p + 2);
rt[2] = *(p + 1);
rt[3] = *(p + 0);
if (endian == Endian.Little)
{
fixed (byte* ptr = rt)
*((int*)ptr) = value;
}
else
{
byte* p = (byte*)&value;
rt[0] = *(p + 3);
rt[1] = *(p + 2);
rt[2] = *(p + 1);
rt[3] = *(p + 0);
}
return rt;
}
public static unsafe byte[] ToBytes(this short value)
public static unsafe byte[] ToBytes(this short value, Endian endian)
{
var rt = new byte[2];
byte* p = (byte*)&value;
if (endian == Endian.Little)
{
fixed (byte* ptr = rt)
*((short*)ptr) = value;
}
else
{
byte* p = (byte*)&value;
rt[0] = *(p + 1);
rt[1] = *(p + 0);
rt[0] = *(p + 1);
rt[1] = *(p + 0);
}
return rt;
}
public static unsafe byte[] ToBytes(this float value)
public static unsafe byte[] ToBytes(this float value, Endian endian)
{
var rt = new byte[4];
//float rt = 0;
byte* p = (byte*)&value;
rt[0] = *(p + 3);
rt[1] = *(p + 2);
rt[2] = *(p + 1);
rt[3] = *(p);
if (endian == Endian.Little)
{
fixed (byte* ptr = rt)
*((float*)ptr) = value;
}
else
{
byte* p = (byte*)&value;
rt[0] = *(p + 3);
rt[1] = *(p + 2);
rt[2] = *(p + 1);
rt[3] = *(p);
}
return rt;
}
@ -406,122 +312,153 @@ public static class DC // Data Converter
public static byte[] ToBytes(this string value)
{
return Encoding.UTF8.GetBytes(value);
}
public unsafe static byte[] ToBytes(this double value)
public unsafe static byte[] ToBytes(this double value, Endian endian)
{
var rt = new byte[8];
if (endian == Endian.Little)
{
fixed (byte* ptr = rt)
*((double*)ptr) = value;
}
else
{
byte* p = (byte*)&value;
byte* p = (byte*)&value;
rt[0] = *(p + 7);
rt[1] = *(p + 6);
rt[2] = *(p + 5);
rt[3] = *(p + 4);
rt[4] = *(p + 3);
rt[5] = *(p + 2);
rt[6] = *(p + 1);
rt[7] = *(p + 0);
rt[0] = *(p + 7);
rt[1] = *(p + 6);
rt[2] = *(p + 5);
rt[3] = *(p + 4);
rt[4] = *(p + 3);
rt[5] = *(p + 2);
rt[6] = *(p + 1);
rt[7] = *(p + 0);
}
return rt;
}
public static unsafe byte[] ToBytes(this long value)
public static unsafe byte[] ToBytes(this long value, Endian endian)
{
var rt = new byte[8];
if (endian == Endian.Little)
{
fixed (byte* ptr = rt)
*((long*)ptr) = value;
}
else
{
byte* p = (byte*)&value;
byte* p = (byte*)&value;
rt[0] = *(p + 7);
rt[1] = *(p + 6);
rt[2] = *(p + 5);
rt[3] = *(p + 4);
rt[4] = *(p + 3);
rt[5] = *(p + 2);
rt[6] = *(p + 1);
rt[7] = *(p + 0);
rt[0] = *(p + 7);
rt[1] = *(p + 6);
rt[2] = *(p + 5);
rt[3] = *(p + 4);
rt[4] = *(p + 3);
rt[5] = *(p + 2);
rt[6] = *(p + 1);
rt[7] = *(p + 0);
}
return rt;
}
public static unsafe byte[] ToBytes(this DateTime value)
{
var rt = new byte[8];
var v = value.ToUniversalTime().Ticks;
byte* p = (byte*)&v;
rt[0] = *(p + 7);
rt[1] = *(p + 6);
rt[2] = *(p + 5);
rt[3] = *(p + 4);
rt[4] = *(p + 3);
rt[5] = *(p + 2);
rt[6] = *(p + 1);
rt[7] = *(p + 0);
fixed (byte* ptr = rt)
*((long*)ptr) = v;
return rt;
}
public static unsafe byte[] ToBytes(this ulong value)
public static unsafe byte[] ToBytes(this ulong value, Endian endia)
{
var rt = new byte[8];
if (endia == Endian.Little)
{
fixed (byte* ptr = rt)
*((ulong*)ptr) = value;
}
else
{
byte* p = (byte*)&value;
byte* p = (byte*)&value;
rt[0] = *(p + 7);
rt[1] = *(p + 6);
rt[2] = *(p + 5);
rt[3] = *(p + 4);
rt[4] = *(p + 3);
rt[5] = *(p + 2);
rt[6] = *(p + 1);
rt[7] = *(p + 0);
rt[0] = *(p + 7);
rt[1] = *(p + 6);
rt[2] = *(p + 5);
rt[3] = *(p + 4);
rt[4] = *(p + 3);
rt[5] = *(p + 2);
rt[6] = *(p + 1);
rt[7] = *(p + 0);
}
return rt;
}
public static unsafe byte[] ToBytes(this uint value)
public static unsafe byte[] ToBytes(this uint value, Endian endian)
{
var rt = new byte[4];
if (endian == Endian.Little)
{
fixed (byte* ptr = rt)
*((uint*)ptr) = value;
}
else
{
byte* p = (byte*)&value;
byte* p = (byte*)&value;
rt[0] = *(p + 3);
rt[1] = *(p + 2);
rt[2] = *(p + 1);
rt[3] = *(p + 0);
rt[0] = *(p + 3);
rt[1] = *(p + 2);
rt[2] = *(p + 1);
rt[3] = *(p + 0);
}
return rt;
}
public static unsafe byte[] ToBytes(this ushort value)
public static unsafe byte[] ToBytes(this ushort value, Endian endian)
{
var rt = new byte[2];
if (endian == Endian.Little)
{
fixed (byte* ptr = rt)
*((ushort*)ptr) = value;
}
else
{
byte* p = (byte*)&value;
byte* p = (byte*)&value;
rt[0] = *(p + 1);
rt[1] = *(p);
rt[0] = *(p + 1);
rt[1] = *(p);
}
return rt;
}
public static byte[] ToBytes(this decimal value)
public static unsafe byte[] ToBytes(this decimal value, Endian endian)
{
byte[] ret = new byte[0];// BitConverter.GetBytes(value);
var rt = new byte[16];
fixed (byte* ptr = rt)
*((decimal*)ptr) = value;
Array.Reverse(ret);
if (endian == Endian.Big)
Array.Reverse(rt);
return ret;
return rt;
}
public static string ToHex(this byte[] ba)
@ -533,22 +470,10 @@ public static class DC // Data Converter
public static string ToHex(this byte[] ba, uint offset, uint length, string separator = " ")
{
if (separator == null)
separator = "";
return string.Join(separator, ba.Skip((int)offset).Take((int)length).Select(x => x.ToString("x2")).ToArray());
//StringBuilder hex = new StringBuilder((int)length * 2);
//for (var i = offset; i < offset + length; i++)
//{
// hex.AppendFormat("{0:x2}", ba[i]);
// if (separator != null)
// hex.Append(separator);
//}
//return hex.ToString();
}
public static byte[] FromHex(string hexString, string separator = " ")
@ -639,240 +564,186 @@ public static class DC // Data Converter
return (sbyte)data[offset];
}
public static sbyte[] GetInt8Array(this byte[] data, uint offset, uint length)
{
var rt = new sbyte[length];
Buffer.BlockCopy(data, (int)offset, rt, 0, (int)length);
return rt;
}
public static byte GetUInt8(this byte[] data, uint offset)
{
return data[offset];
}
public static byte[] GetUInt8Array(this byte[] data, uint offset, uint length)
public static unsafe short GetInt16(this byte[] data, uint offset, Endian endian)
{
var rt = new byte[length];
Buffer.BlockCopy(data, (int)offset, rt, 0, (int)length);
return rt;
}
public static Int16 GetInt16(this byte[] data, uint offset)
{
return (Int16)((data[offset] << 8) | data[offset + 1]);
}
public static Int16[] GetInt16Array(this byte[] data, uint offset, uint length)
{
var j = 0; var end = offset + length;
var rt = new Int16[length / 2];
for (var i = offset; i < end; i += 2)
rt[j++] = GetInt16(data, i);
return rt;
}
public static UInt16 GetUInt16(this byte[] data, uint offset)
{
return (UInt16)((data[offset] << 8) | data[offset + 1]);
}
public static UInt16[] GetUInt16Array(this byte[] data, uint offset, uint length)
{
var j = 0; var end = offset + length;
var rt = new UInt16[length / 2];
for (var i = offset; i < end; i += 2)
rt[j++] = GetUInt16(data, i);
return rt;
}
public static Int32 GetInt32(this byte[] data, uint offset)
{
return (Int32)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]);
}
public static Int32[] GetInt32Array(this byte[] data, uint offset, uint length)
{
var j = 0; var end = offset + length;
var rt = new Int32[length / 4];
for (var i = offset; i < end; i += 4)
rt[j++] = GetInt32(data, i);
return rt;
}
public static UInt32 GetUInt32(this byte[] data, uint offset)
{
return (UInt32)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]);
}
public static UInt32[] GetUInt32Array(this byte[] data, uint offset, uint length)
{
var j = 0; var end = offset + length;
var rt = new UInt32[length / 4];
for (var i = offset; i < end; i += 4)
rt[j++] = GetUInt16(data, i);
return rt;
if (endian == Endian.Little)
{
fixed (byte* ptr = &data[offset])
return *(short*)ptr;
}
else
{
return (Int16)((data[offset] << 8) | data[offset + 1]);
}
}
public static unsafe UInt64 GetUInt64(this byte[] data, uint offset)
public static unsafe ushort GetUInt16(this byte[] data, uint offset, Endian endian)
{
UInt64 rt = 0;
byte* p = (byte*)&rt;
*(p + 7) = data[offset++];
*(p + 6) = data[offset++];
*(p + 5) = data[offset++];
*(p + 4) = data[offset++];
*(p + 3) = data[offset++];
*(p + 2) = data[offset++];
*(p + 1) = data[offset++];
*(p) = data[offset++];
return rt;
if (endian == Endian.Little)
{
fixed (byte* ptr = &data[offset])
return *(ushort*)ptr;
}
else
{
return (UInt16)((data[offset] << 8) | data[offset + 1]);
}
}
public static Int64[] GetInt64Array(this byte[] data, uint offset, uint length)
public static unsafe int GetInt32(this byte[] data, uint offset, Endian endian)
{
var j = 0; var end = offset + length;
var rt = new Int64[length / 8];
for (var i = offset; i < end; i += 8)
rt[j++] = GetInt64(data, i);
return rt;
if (endian == Endian.Little)
{
fixed (byte* ptr = &data[offset])
return *(int*)ptr;
}
else
{
return (Int32)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]);
}
}
public static unsafe Int64 GetInt64(this byte[] data, uint offset)
public static unsafe uint GetUInt32(this byte[] data, uint offset, Endian endian)
{
Int64 rt = 0;
byte* p = (byte*)&rt;
*(p + 7) = data[offset++];
*(p + 6) = data[offset++];
*(p + 5) = data[offset++];
*(p + 4) = data[offset++];
*(p + 3) = data[offset++];
*(p + 2) = data[offset++];
*(p + 1) = data[offset++];
*(p) = data[offset++];
return rt;
/* Or
return (Int64)(
(data[offset] << 56)
| (data[offset + 1] << 48)
| (data[offset + 2] << 40)
| (data[offset + 3] << 32)
| (data[offset + 4] << 24)
| (data[offset + 5] << 16)
| (data[offset + 6] << 8)
| (data[offset + 7])
);
*/
if (endian == Endian.Little)
{
fixed (byte* ptr = &data[offset])
return *(uint*)ptr;
}
else
{
return (uint)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]);
}
}
public static UInt64[] GetUInt64Array(this byte[] data, uint offset, uint length)
public static unsafe ulong GetUInt64(this byte[] data, uint offset, Endian endian)
{
var j = 0; var end = offset + length;
var rt = new UInt64[length / 8];
if (endian == Endian.Little)
{
fixed (byte* ptr = &data[offset])
return *(ulong*)ptr;
}
else
{
UInt64 rt = 0;
byte* p = (byte*)&rt;
for (var i = offset; i < end; i += 8)
rt[j++] = GetUInt64(data, i);
*(p + 7) = data[offset++];
*(p + 6) = data[offset++];
*(p + 5) = data[offset++];
*(p + 4) = data[offset++];
*(p + 3) = data[offset++];
*(p + 2) = data[offset++];
*(p + 1) = data[offset++];
*(p) = data[offset++];
return rt;
return rt;
}
}
public static unsafe float GetFloat32(this byte[] data, uint offset)
public static unsafe long GetInt64(this byte[] data, uint offset, Endian endian)
{
float rt = 0;
byte* p = (byte*)&rt;
*p = data[offset + 3];
*(p + 1) = data[offset + 2];
*(p + 2) = data[offset + 1];
*(p + 3) = data[offset];
return rt;
if (endian == Endian.Little)
{
fixed (byte* ptr = &data[offset])
return *(long*)ptr;
}
else
{
Int64 rt = 0;
byte* p = (byte*)&rt;
*(p + 7) = data[offset++];
*(p + 6) = data[offset++];
*(p + 5) = data[offset++];
*(p + 4) = data[offset++];
*(p + 3) = data[offset++];
*(p + 2) = data[offset++];
*(p + 1) = data[offset++];
*(p) = data[offset++];
return rt;
}
}
public static float[] GetFloat32Array(this byte[] data, uint offset, uint length)
public static unsafe float GetFloat32(this byte[] data, uint offset, Endian endian)
{
var j = 0; var end = offset + length;
var rt = new float[length / 4];
if (endian == Endian.Little)
{
fixed (byte* ptr = &data[offset])
return *(float*)ptr;
}
else
{
float rt = 0;
byte* p = (byte*)&rt;
*p = data[offset + 3];
*(p + 1) = data[offset + 2];
*(p + 2) = data[offset + 1];
*(p + 3) = data[offset];
return rt;
for (var i = offset; i < end; i += 4)
rt[j++] = GetFloat32(data, i);
return rt;
}
}
public static unsafe double GetFloat64(this byte[] data, uint offset)
public static unsafe double GetFloat64(this byte[] data, uint offset, Endian endian)
{
double rt = 0;
byte* p = (byte*)&rt;
if (endian == Endian.Little)
{
fixed (byte* ptr = &data[offset])
return *(double*)ptr;
}
else
{
double rt = 0;
byte* p = (byte*)&rt;
*(p + 7) = data[offset++];
*(p + 6) = data[offset++];
*(p + 5) = data[offset++];
*(p + 4) = data[offset++];
*(p + 3) = data[offset++];
*(p + 2) = data[offset++];
*(p + 1) = data[offset++];
*(p) = data[offset++];
*(p + 7) = data[offset++];
*(p + 6) = data[offset++];
*(p + 5) = data[offset++];
*(p + 4) = data[offset++];
*(p + 3) = data[offset++];
*(p + 2) = data[offset++];
*(p + 1) = data[offset++];
*(p) = data[offset++];
return rt;
return rt;
}
}
public static double[] GetFloat64Array(this byte[] data, uint offset, uint length)
{
var j = 0; var end = offset + length;
var rt = new double[length / 8];
for (var i = offset; i < end; i += 8)
rt[j++] = GetFloat64(data, i);
return rt;
}
public static bool GetBoolean(this byte[] data, uint offset)
{
return data[offset] > 0;
}
public static bool[] GetBooleanArray(this byte[] data, uint offset, uint length)
{
var rt = new bool[length];
for (var i = 0; i < length; i++)
rt[i] = data[offset + i] > 0;
return rt;
}
public static char GetChar(this byte[] data, uint offset)
{
return Convert.ToChar(((data[offset] << 8) | data[offset + 1]));
}
public static char[] GetCharArray(this byte[] data, uint offset, uint length)
{
var j = 0; var end = offset + length;
var rt = new char[length / 2];
for (var i = offset; i < end; i += 2)
rt[j++] = GetChar(data, i);
return rt;
}
public static string GetString(this byte[] data, uint offset, uint length)
{
@ -887,7 +758,7 @@ public static class DC // Data Converter
while (i < length)
{
var cl = GetUInt32(data, offset + i);
var cl = GetUInt32(data, offset + i, Endian.Little);
i += 4;
ar.Add(Encoding.UTF8.GetString(data, (int)(offset + i), (int)cl));
i += cl;
@ -901,69 +772,24 @@ public static class DC // Data Converter
return new Guid(Clip(data, offset, 16));
}
public static Guid[] GetGuidArray(this byte[] data, uint offset, uint length)
public static DateTime GetDateTime(this byte[] data, uint offset, Endian endian)
{
var j = 0; var end = offset + length;
var rt = new Guid[length / 16];
for (var i = offset; i < end; i += 16)
rt[j++] = GetGuid(data, i);
return rt;
}
public static DateTime GetDateTime(this byte[] data, uint offset)
{
var ticks = GetInt64(data, offset);
var ticks = GetInt64(data, offset, endian);
return new DateTime(ticks, DateTimeKind.Utc);
}
public static DateTime[] GetDateTimeArray(this byte[] data, uint offset, uint length)
{
var j = 0; var end = offset + length;
var rt = new DateTime[length / 8];
for (var i = offset; i < end; i += 8)
rt[j++] = GetDateTime(data, i);
return rt;
}
public static IPAddress GetIPv4Address(this byte[] data, uint offset)
{
return new IPAddress((long)GetUInt32(data, offset));
return new IPAddress((long)GetUInt32(data, offset, Endian.Little));
}
public static IPAddress[] GetIPv4AddressArray(this byte[] data, uint offset, uint length)
{
var j = 0; var end = offset + length;
var rt = new IPAddress[length / 4];
for (var i = offset; i < end; i += 4)
rt[j++] = GetIPv6Address(data, i);
return rt;
}
public static IPAddress GetIPv6Address(this byte[] data, uint offset)
{
return new IPAddress(Clip(data, offset, 16));
}
public static IPAddress[] GetIPv6AddressArray(this byte[] data, uint offset, uint length)
{
var j = 0; var end = offset + length;
var rt = new IPAddress[length / 16];
for (var i = offset; i < end; i += 16)
rt[j++] = GetIPv6Address(data, i);
return rt;
}
public static byte[] Clip(this byte[] data, uint offset, uint length)
{
if (data.Length < offset + length)

View File

@ -0,0 +1,554 @@
using Esiur.Core;
using Esiur.Net.IIP;
using Esiur.Resource;
using System;
using System.Collections.Generic;
using System.Text;
using Esiur.Data;
using Esiur.Resource.Template;
using System.Linq;
namespace Esiur.Data;
public static class DataDeserializer
{
public static AsyncReply NullParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
return new AsyncReply(null);
}
public static AsyncReply BooleanTrueParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
return new AsyncReply<bool>(true);
}
public static AsyncReply BooleanFalseParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
return new AsyncReply<bool>(false);
}
public static AsyncReply NotModifiedParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
return new AsyncReply<NotModified>(new NotModified());
}
public static AsyncReply ByteParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
return new AsyncReply<byte>(data[offset]);
}
public static AsyncReply SByteParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
return new AsyncReply<sbyte>((sbyte)data[offset]);
}
public static unsafe AsyncReply Char16Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<char>(*(char*)ptr);
}
public static AsyncReply Char8Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
return new AsyncReply<char>((char)data[offset]);
}
public static unsafe AsyncReply Int16Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<short>(*(short*)ptr);
}
public static unsafe AsyncReply UInt16Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<ushort>(*(ushort*)ptr);
}
public static unsafe AsyncReply Int32Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<int>(*(int*)ptr);
}
public static unsafe AsyncReply UInt32Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<uint>(*(uint*)ptr);
}
public static unsafe AsyncReply Float32Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<float>(*(float*)ptr);
}
public static unsafe AsyncReply Float64Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<double>(*(double*)ptr);
}
public static unsafe AsyncReply Float128Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<decimal>(*(decimal*)ptr);
}
public static unsafe AsyncReply Int128Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<decimal>(*(decimal*)ptr);
}
public static unsafe AsyncReply UInt128Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<decimal>(*(decimal*)ptr);
}
public static unsafe AsyncReply Int64Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<long>(*(long*)ptr);
}
public static unsafe AsyncReply UInt64Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<ulong>(*(ulong*)ptr);
}
public static unsafe AsyncReply DateTimeParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return new AsyncReply<DateTime>(new DateTime(*(long*)ptr, DateTimeKind.Utc));
}
public static unsafe AsyncReply ResourceParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return connection.Fetch(*(uint*)ptr);
}
public static unsafe AsyncReply LocalResourceParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
fixed (byte* ptr = &data[offset])
return Warehouse.GetById(*(uint*)ptr);
}
public static unsafe AsyncReply RawDataParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
return new AsyncReply<byte[]>(data.Clip(offset, length));
}
public static unsafe AsyncReply StringParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
return new AsyncReply<string>(data.GetString(offset, length));
}
public static unsafe AsyncReply RecordParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
var reply = new AsyncReply<IRecord>();
var classId = data.GetGuid(offset);
offset += 16;
length -= 16;
var template = Warehouse.GetTemplateByClassId((Guid)classId, TemplateType.Record);
if (template != null)
{
//ListParser(data, offset, length, connection)
ListParser(data, offset, length, connection).Then(r =>
{
var ar = (object[])r;
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);
template.Properties[i].PropertyInfo.SetValue(record, v);
} catch ( Exception ex)
{
Console.WriteLine(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);
}
});
}
else
{
connection.GetTemplate((Guid)classId).Then(tmp =>
{
ListParser(data, offset, length, connection).Then(r =>
{
var ar = (object[])r;
var record = new Record();
for (var i = 0; i < tmp.Properties.Length; i++)
record.Add(tmp.Properties[i].Name, ar[i]);
reply.Trigger(record);
});
}).Error(x => reply.TriggerError(x));
}
return reply;
}
public static unsafe AsyncReply ConstantParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
throw new NotImplementedException();
}
public static unsafe AsyncReply EnumParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
var classId = data.GetGuid(offset);
offset += 16;
var index = data[offset++];
var template = Warehouse.GetTemplateByClassId((Guid)classId, TemplateType.Enum);
if (template != null)
{
return new AsyncReply(template.Constants[index].Value);
}
else
{
var reply = new AsyncReply();
connection.GetTemplate((Guid)classId).Then(tmp =>
{
reply.Trigger(tmp.Constants[index].Value);
}).Error(x => reply.TriggerError(x));
return reply;
}
}
public static AsyncReply RecordListParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
var rt = new AsyncBag<IRecord>();
while (length > 0)
{
var (cs, reply) = Codec.Parse(data, offset, connection);
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 AsyncReply ResourceListParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
var rt = new AsyncBag<IResource>();
while (length > 0)
{
var (cs, reply) = Codec.Parse(data, offset, connection);
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 AsyncBag<object> ListParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
var rt = new AsyncBag<object>();
while (length > 0)
{
var (cs, reply) = Codec.Parse(data, offset, connection);
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 AsyncReply TypedMapParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
// get key type
var (keyCs, keyRepType) = RepresentationType.Parse(data, offset);
offset += keyCs;
length -= keyCs;
var (valueCs, valueRepType) = RepresentationType.Parse(data, offset);
offset += valueCs;
length -= valueCs;
var map = (IMap)Activator.CreateInstance(typeof(Map<,>).MakeGenericType(keyRepType.GetRuntimeType(), valueRepType.GetRuntimeType()));
var rt = new AsyncReply();
var results = new AsyncBag<object>();
while (length > 0)
{
var (cs, reply) = Codec.Parse(data, offset, connection);
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 AsyncReply TupleParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
var results = new AsyncBag<object>();
var rt = new AsyncReply();
var tupleSize = data[offset++];
length--;
var types = new List<Type>();
for (var i = 0; i < tupleSize; i++)
{
var (cs, rep) = RepresentationType.Parse(data, offset);
types.Add(rep.GetRuntimeType());
offset += cs;
length -= cs;
}
while (length > 0)
{
var (cs, reply) = Codec.Parse(data, offset, connection);
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]));
}
});
return rt;
}
public static AsyncReply TypedListParser(byte[] data, uint offset, uint length, DistributedConnection connection)
{
var rt = new AsyncBag<object>();
// get the type
var (hdrCs, rep) = RepresentationType.Parse(data, offset);
offset += hdrCs;
length -= hdrCs;
var runtimeType = rep.GetRuntimeType();
rt.ArrayType = runtimeType;
while (length > 0)
{
var (cs, reply) = Codec.Parse(data, offset, connection);
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 AsyncBag<PropertyValue> PropertyValueArrayParser(byte[] data, uint offset, uint length, DistributedConnection connection)//, bool ageIncluded = true)
{
var rt = new AsyncBag<PropertyValue>();
ListParser(data, offset, length, connection).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>) PropertyValueParser(byte[] data, uint offset, DistributedConnection connection)//, 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.Parse(data, offset, connection);
results.Then(value =>
{
reply.Trigger(new PropertyValue(value, age, date));
});
return (16 + valueSize, reply);
}
public static AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> HistoryParser(byte[] data, uint offset, uint length, IResource resource, DistributedConnection connection)
{
//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) = PropertyValueParser(data, offset, connection);
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;
}
}

View File

@ -0,0 +1,416 @@
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.Linq;
using System.Text;
namespace Esiur.Data;
public static class DataSerializer
{
public delegate byte[] Serializer(object value);
public static unsafe (TransmissionTypeIdentifier, byte[]) Int32Composer(object value, DistributedConnection connection)
{
var v = (int)value;
var rt = new byte[4];
fixed (byte* ptr = rt)
*((int*)ptr) = v;
return (TransmissionTypeIdentifier.Int32, rt);
}
public static unsafe (TransmissionTypeIdentifier, byte[]) UInt32Composer(object value, DistributedConnection connection)
{
var v = (uint)value;
var rt = new byte[4];
fixed (byte* ptr = rt)
*((uint*)ptr) = v;
return (TransmissionTypeIdentifier.UInt32, rt);
}
public static unsafe (TransmissionTypeIdentifier, byte[]) Int16Composer(object value, DistributedConnection connection)
{
var v = (short)value;
var rt = new byte[2];
fixed (byte* ptr = rt)
*((short*)ptr) = v;
return (TransmissionTypeIdentifier.Int16, rt);
}
public static unsafe (TransmissionTypeIdentifier, byte[]) UInt16Composer(object value, DistributedConnection connection)
{
var v = (ushort)value;
var rt = new byte[2];
fixed (byte* ptr = rt)
*((ushort*)ptr) = v;
return (TransmissionTypeIdentifier.UInt16, rt);
}
public static unsafe (TransmissionTypeIdentifier, byte[]) Float32Composer(object value, DistributedConnection connection)
{
var v = (float)value;
var rt = new byte[4];
fixed (byte* ptr = rt)
*((float*)ptr) = v;
return (TransmissionTypeIdentifier.Float32, rt);
}
public static unsafe (TransmissionTypeIdentifier, byte[]) Float64Composer(object value, DistributedConnection connection)
{
var v = (double)value;
var rt = new byte[8];
fixed (byte* ptr = rt)
*((double*)ptr) = v;
return (TransmissionTypeIdentifier.Float64, rt);
}
public static unsafe (TransmissionTypeIdentifier, byte[]) Int64Composer(object value, DistributedConnection connection)
{
var v = (long)value;
var rt = new byte[8];
fixed (byte* ptr = rt)
*((long*)ptr) = v;
return (TransmissionTypeIdentifier.Int64, rt);
}
public static unsafe (TransmissionTypeIdentifier, byte[]) UIn64Composer(object value, DistributedConnection connection)
{
var v = (ulong)value;
var rt = new byte[8];
fixed (byte* ptr = rt)
*((ulong*)ptr) = v;
return (TransmissionTypeIdentifier.UInt64, rt);
}
public static unsafe (TransmissionTypeIdentifier, byte[]) DateTimeComposer(object value, DistributedConnection connection)
{
var v = ((DateTime)value).ToUniversalTime().Ticks;
var rt = new byte[8];
fixed (byte* ptr = rt)
*((long*)ptr) = v;
return (TransmissionTypeIdentifier.DateTime, rt);
}
public static unsafe (TransmissionTypeIdentifier, byte[]) Float128Composer(object value, DistributedConnection connection)
{
var v = (decimal)value;
var rt = new byte[16];
fixed (byte* ptr = rt)
*((decimal*)ptr) = v;
return (TransmissionTypeIdentifier.Float128, rt);
}
public static (TransmissionTypeIdentifier, byte[]) StringComposer(object value, DistributedConnection connection)
{
return (TransmissionTypeIdentifier.String, Encoding.UTF8.GetBytes((string)value));
}
public static (TransmissionTypeIdentifier, byte[]) EnumComposer(object value, DistributedConnection connection)
{
if (value == null)
return (TransmissionTypeIdentifier.Null, new byte[0]);
var template = Warehouse.GetTemplateByType(value.GetType());
var intVal = Convert.ChangeType(value, (value as Enum).GetTypeCode());
var ct = template.Constants.FirstOrDefault(x => x.Value.Equals(intVal));
if (ct == null)
return (TransmissionTypeIdentifier.Null, new byte[0]);
var rt = new List<byte>();
rt.AddRange(template.ClassId.ToByteArray());
rt.Add(ct.Index);
return (TransmissionTypeIdentifier.Enum, rt.ToArray());
}
public static (TransmissionTypeIdentifier, byte[]) UInt8Composer(object value, DistributedConnection connection)
{
return (TransmissionTypeIdentifier.UInt8, new byte[] { (byte)value });
}
public static (TransmissionTypeIdentifier, byte[]) Int8Composer(object value, DistributedConnection connection)
{
return (TransmissionTypeIdentifier.Int8, new byte[] { (byte)(sbyte)value });
}
public static unsafe (TransmissionTypeIdentifier, byte[]) Char8Composer(object value, DistributedConnection connection)
{
return (TransmissionTypeIdentifier.Char8, new byte[] { (byte)(char)value });
}
public static unsafe (TransmissionTypeIdentifier, byte[]) Char16Composer(object value, DistributedConnection connection)
{
var v = (char)value;
var rt = new byte[2];
fixed (byte* ptr = rt)
*((char*)ptr) = v;
return (TransmissionTypeIdentifier.Char16, rt);
}
public static (TransmissionTypeIdentifier, byte[]) BoolComposer(object value, DistributedConnection connection)
{
return ((bool)value ? TransmissionTypeIdentifier.True : TransmissionTypeIdentifier.False, new byte[0]);
}
public static (TransmissionTypeIdentifier, byte[]) NotModifiedComposer(object value, DistributedConnection connection)
{
return (TransmissionTypeIdentifier.NotModified, new byte[0]);
}
public static (TransmissionTypeIdentifier, byte[]) RawDataComposerFromArray(object value, DistributedConnection connection)
{
return (TransmissionTypeIdentifier.RawData, (byte[])value);
}
public static (TransmissionTypeIdentifier, byte[]) RawDataComposerFromList(dynamic value, DistributedConnection connection)
{
return (TransmissionTypeIdentifier.RawData, (value as List<byte>).ToArray());
}
//public static (TransmissionTypeIdentifier, byte[]) ListComposerFromArray(dynamic value, DistributedConnection connection)
//{
// var rt = new List<byte>();
// var array = (object[])value;
// for (var i = 0; i < array.Length; i++)
// rt.AddRange(Codec.Compose(array[i], connection));
// return (TransmissionTypeIdentifier.List, rt.ToArray());
//}
public static (TransmissionTypeIdentifier, byte[]) ListComposer(object value, DistributedConnection connection)
{
var rt = ArrayComposer((IEnumerable)value, connection);
if (rt == null)
return (TransmissionTypeIdentifier.Null, new byte[0]);
else
return (TransmissionTypeIdentifier.List, rt);
//var rt = new List<byte>();
//var list = (IEnumerable)value;// ((List<object>)value);
//foreach (var o in list)
// rt.AddRange(Codec.Compose(o, connection));
//return (TransmissionTypeIdentifier.List, rt.ToArray());
}
public static (TransmissionTypeIdentifier, byte[]) TypedListComposer(IEnumerable value, Type type, DistributedConnection connection)
{
var composed = ArrayComposer((IEnumerable)value, connection);
if (composed == null)
return (TransmissionTypeIdentifier.Null, new byte[0]);
var header = RepresentationType.FromType(type).Compose();
var rt = new List<byte>();
rt.AddRange(header);
rt.AddRange(composed);
return (TransmissionTypeIdentifier.TypedList, rt.ToArray());
}
//public static byte[] PropertyValueComposer(PropertyValue propertyValue, DistributedConnection connection)//, bool includeAge = true)
//{
// var rt = new BinaryList();
// return
// .AddUInt64(propertyValue.Age)
// .AddDateTime(propertyValue.Date)
// .AddUInt8Array(Codec.Compose(propertyValue.Value, connection))
// .ToArray();
//}
public static (TransmissionTypeIdentifier, byte[]) PropertyValueArrayComposer(object value, DistributedConnection connection)
{
if (value == null)
return (TransmissionTypeIdentifier.Null, new byte[0]);
var rt = new List<byte>();
var ar = value as PropertyValue[];
foreach (var pv in ar)
{
rt.AddRange(Codec.Compose(pv.Age, connection));
rt.AddRange(Codec.Compose(pv.Date, connection));
rt.AddRange(Codec.Compose(pv.Value, connection));
}
return (TransmissionTypeIdentifier.List, rt.ToArray());
}
public static (TransmissionTypeIdentifier, byte[]) TypedMapComposer(object value, Type keyType, Type valueType, DistributedConnection connection)
{
if (value == null)
return (TransmissionTypeIdentifier.Null, new byte[0]);
var kt = RepresentationType.FromType(keyType).Compose();
var vt = RepresentationType.FromType(valueType).Compose();
var rt = new List<byte>();
rt.AddRange(kt);
rt.AddRange(vt);
var map = (IMap)value;
foreach(var el in map.Serialize())
rt.AddRange(Codec.Compose(el, connection));
return (TransmissionTypeIdentifier.TypedMap, rt.ToArray());
}
public static byte[] ArrayComposer(IEnumerable value, DistributedConnection connection)
{
if (value == null)
return null;
var rt = new List<byte>();
foreach (var i in value)
rt.AddRange(Codec.Compose(i, connection));
return rt.ToArray();
}
public static (TransmissionTypeIdentifier, byte[]) ResourceListComposer(object value, DistributedConnection connection)
{
if (value == null)
return (TransmissionTypeIdentifier.Null, new byte[0]);
return (TransmissionTypeIdentifier.ResourceList, ArrayComposer((IEnumerable)value, connection));
}
public static (TransmissionTypeIdentifier, byte[]) RecordListComposer(object value, DistributedConnection connection)
{
if (value == null)
return (TransmissionTypeIdentifier.Null, new byte[0]);
return (TransmissionTypeIdentifier.RecordList, ArrayComposer((IEnumerable)value, connection));
}
public static unsafe (TransmissionTypeIdentifier, byte[]) ResourceComposer(object value, DistributedConnection connection)
{
var resource = (IResource)value;
var rt = new byte[4];
if (Codec.IsLocalResource(resource, connection))
{
fixed (byte* ptr = rt)
*((uint*)ptr) = (resource as DistributedResource).Id;
return (TransmissionTypeIdentifier.ResourceLocal, rt);
}
else
{
//rt.Append((value as IResource).Instance.Template.ClassId, (value as IResource).Instance.Id);
connection.cache.Add(value as IResource, DateTime.UtcNow);
fixed (byte* ptr = rt)
*((uint*)ptr) = resource.Instance.Id;
return (TransmissionTypeIdentifier.Resource, rt);
}
}
public static unsafe (TransmissionTypeIdentifier, byte[]) MapComposer(object value, DistributedConnection connection)
{
if (value == null)
return (TransmissionTypeIdentifier.Null, new byte[0]);
var rt = new List<byte>();
var map = (IMap)value;
foreach (var el in map.Serialize())
rt.AddRange(Codec.Compose(el, connection));
return (TransmissionTypeIdentifier.Map, rt.ToArray());
}
public static unsafe (TransmissionTypeIdentifier, byte[]) RecordComposer(object value, DistributedConnection connection)
{
var rt = new List<byte>();// BinaryList();
var record = (IRecord)value;
var template = Warehouse.GetTemplateByType(record.GetType());
rt.AddRange(template.ClassId.ToByteArray());
foreach (var pt in template.Properties)
{
var propValue = pt.PropertyInfo.GetValue(record, null);
rt.AddRange(Codec.Compose(propValue, connection));
}
return (TransmissionTypeIdentifier.Record, rt.ToArray());
}
public static byte[] HistoryComposer(KeyList<PropertyTemplate, PropertyValue[]> history,
DistributedConnection connection, bool prependLength = false)
{
//@TODO:Test
var rt = new BinaryList();
for (var i = 0; i < history.Count; i++)
rt.AddUInt8(history.Keys.ElementAt(i).Index)
.AddUInt8Array(Codec.Compose(history.Values.ElementAt(i), connection));
if (prependLength)
rt.InsertInt32(0, rt.Length);
return rt.ToArray();
}
public static (TransmissionTypeIdentifier, byte[]) TupleComposer(object value, DistributedConnection connection)
{
if (value == null)
return (TransmissionTypeIdentifier.Null, new byte[0]);
var rt = new List<byte>();
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();
rt.Add((byte)list.Length);
foreach (var t in types)
rt.AddRange(t);
var composed = ArrayComposer(list, connection);
if (composed == null)
return (TransmissionTypeIdentifier.Null, new byte[0]);
else
{
rt.AddRange(composed);
return (TransmissionTypeIdentifier.Tuple, rt.ToArray());
}
}
}

12
Esiur/Data/Endian.cs Normal file
View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Data
{
public enum Endian
{
Big,
Little
}
}

View File

@ -229,7 +229,7 @@ public class KeyList<KT, T> : IEnumerable<KeyValuePair<KT, T>>
#if NETSTANDARD
removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()));
#else
removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T)));
removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T)));
#endif
this.Owner = owner;

248
Esiur/Data/Map.cs Normal file
View File

@ -0,0 +1,248 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Esiur.Data;
using Esiur.Misc;
using Esiur.Core;
using System.Reflection;
using System.Dynamic;
namespace Esiur.Data;
//public class Map : IEnumerable<KeyValuePair<object, object>>
//{
// private Dictionary<object, object> dic = new();
// public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
// {
// return dic.GetEnumerator();
// }
// IEnumerator IEnumerable.GetEnumerator()
// {
// return dic.GetEnumerator();
// }
//}
public interface IMap
{
public void Add(object key, object value);
public void Remove(object key);
public void Clear();
public bool ContainsKey(object key);
public object[] Serialize();
}
public class Map<KT, VT> : IEnumerable<KeyValuePair<KT, VT>>, IMap
{
//public struct StructureMetadata
//{
// public KT[] Keys;
// public VT[] Types;
//}
private Dictionary<KT, VT> dic = new Dictionary<KT, VT>();// StringComparer.OrdinalIgnoreCase);
private object syncRoot = new object();
public bool ContainsKey(KT key)
{
return dic.ContainsKey(key);
}
public override string ToString()
{
var rt = "";
foreach (var kv in dic)
rt += kv.Key + ": " + kv.Value.ToString() + " \r\n";
return rt.TrimEnd('\r', '\n');
}
public Map(Map<KT,VT> source)
{
dic = source.dic;
}
public Map()
{
}
public static Map<KT,VT> FromMap(Map<KT,VT> source, Type destinationType)
{
var rt = Activator.CreateInstance(destinationType) as Map<KT, VT>;
rt.dic = source.dic;
return rt;
}
//public static T FromStructure<T>(Map<KT, VT> source) where T : Map<KT, VT>
//{
// var rt = Activator.CreateInstance<T>();
// rt.dic = source.dic;
// return rt;
//}
// public static explicit operator Map<string, object>(ExpandoObject obj) => FromDynamic(obj);
public static Map<string, object> FromDynamic(ExpandoObject obj)
{
var rt = new Map<string, object>();
foreach (var kv in obj)
rt[kv.Key] = kv.Value;
return rt;
}
public static Map<string,object> FromObject(object obj)
{
var type = obj.GetType();
var st = new Map<string,object>();
var pi = type.GetTypeInfo().GetProperties().Where(x => x.CanRead);
foreach (var p in pi)
st[p.Name] = p.GetValue(obj);
var fi = type.GetTypeInfo().GetFields().Where(x => x.IsPublic);
foreach (var f in fi)
st[f.Name] = f.GetValue(obj);
return st;
// if (obj is Structure)
// return obj as Structure;
// else //if (Codec.IsAnonymous(type))
// {
// var st = new Structure();
// var pi = type.GetTypeInfo().GetProperties().Where(x => x.CanRead);
// foreach (var p in pi)
// st[p.Name] = p.GetValue(obj);
// var fi = type.GetTypeInfo().GetFields().Where(x => x.IsPublic);
// foreach (var f in fi)
// st[f.Name] = f.GetValue(obj);
// return st;
// }
// //else
// // return null;
}
public IEnumerator<KeyValuePair<KT, VT>> GetEnumerator()
{
return dic.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return dic.GetEnumerator();
}
public int Length
{
get { return dic.Count; }
}
public KeyValuePair<KT, VT> At(int index)
{
return dic.ElementAt(index);
}
public object SyncRoot
{
get { return syncRoot; }
}
public KT[] GetKeys() => dic.Keys.ToArray();//GetKeys()
//{
// return dic.Keys.ToArray();
//}
public void Add(KT key, VT value)
{
if (dic.ContainsKey(key))
dic[key] = value;
else
dic.Add(key, value);
}
public void Add(object key, object value)
{
Add((KT)key, (VT)value);
}
public void Remove(object key)
{
Remove((KT)key);
}
public void Clear()
{
dic.Clear();
}
public bool ContainsKey(object key)
{
return ContainsKey((KT)key);
}
public object[] Serialize()
{
var rt = new List<object>();
foreach(var kv in dic)
{
rt.Add(kv.Key);
rt.Add(kv.Value);
}
return rt.ToArray();
}
public VT this[KT index]
{
get
{
if (dic.ContainsKey(index))
return dic[index];
else
return default;
}
set
{
if (dic.ContainsKey(index))
dic[index] = value;
else
dic.Add(index, value);
}
}
}

View File

@ -13,11 +13,11 @@ public class PropertyValue
/// <summary>
/// Get or set date of modification or occurrence.
/// </summary>
public DateTime Date { get; set; }
public DateTime? Date { get; set; }
/// <summary>
/// Get or set property age.
/// </summary>
public ulong Age { get; set; }
public ulong? Age { get; set; }
/// <summary>
/// Create an instance of PropertyValue.
@ -25,7 +25,7 @@ public class PropertyValue
/// <param name="value">Value.</param>
/// <param name="age">Age.</param>
/// <param name="date">Date.</param>
public PropertyValue(object value, ulong age, DateTime date)
public PropertyValue(object value, ulong? age, DateTime? date)
{
Value = value;
Age = age;

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Data;
public enum RecordComparisonResult : byte
{
Null,
Record,
RecordSameType,
Same
}

View 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));
}
}
}
}

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Data;
public enum ResourceComparisonResult
{
Null, // null
Distributed, // resource is distributed
Local, // resource is local
Same, // Same as previous
}

View File

@ -55,7 +55,7 @@ class ResourceJsonConverter : JsonConverter<IResource>
foreach (var pt in resource.Instance.Template.Properties)
{
var rt = pt.PropertyInfo.GetValue(resource, null);
if (rt is DistributedPropertyContext)
if (rt != null && rt.GetType().IsGenericType)
continue;
writer.WritePropertyName(options.PropertyNamingPolicy?.ConvertName(pt.Name) ?? pt.Name);

View File

@ -1,180 +0,0 @@
/*
Copyright (c) 2017 Ahmed Kh. Zamil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Esiur.Data;
using Esiur.Misc;
using Esiur.Core;
using System.Reflection;
using System.Dynamic;
namespace Esiur.Data;
public class Structure : IEnumerable<KeyValuePair<string, object>>
{
public struct StructureMetadata
{
public string[] Keys;
public DataType[] Types;
}
private Dictionary<string, object> dic = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
private object syncRoot = new object();
public bool ContainsKey(string key)
{
return dic.ContainsKey(key);
}
public override string ToString()
{
var rt = "";
foreach (var kv in dic)
rt += kv.Key + ": " + kv.Value.ToString() + " \r\n";
return rt.TrimEnd('\r', '\n');
}
public Structure(Structure source)
{
dic = source.dic;
}
public Structure()
{
}
public static Structure FromStructure(Structure source, Type destinationType)
{
var rt = Activator.CreateInstance(destinationType) as Structure;
rt.dic = source.dic;
return rt;
}
public static T FromStructure<T>(Structure source) where T : Structure
{
var rt = Activator.CreateInstance<T>();
rt.dic = source.dic;
return rt;
}
public static explicit operator Structure(ExpandoObject obj) => FromDynamic(obj);
public static Structure FromDynamic(ExpandoObject obj)
{
var rt = new Structure();
foreach (var kv in obj)
rt[kv.Key] = kv.Value;
return rt;
}
public static Structure FromObject(object obj)
{
var type = obj.GetType();
if (obj is Structure)
return obj as Structure;
else //if (Codec.IsAnonymous(type))
{
var st = new Structure();
var pi = type.GetTypeInfo().GetProperties().Where(x => x.CanRead);
foreach (var p in pi)
st[p.Name] = p.GetValue(obj);
var fi = type.GetTypeInfo().GetFields().Where(x => x.IsPublic);
foreach (var f in fi)
st[f.Name] = f.GetValue(obj);
return st;
}
//else
// return null;
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
return dic.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return dic.GetEnumerator();
}
public int Length
{
get { return dic.Count; }
}
public KeyValuePair<string, object> At(int index)
{
return dic.ElementAt(index);
}
public object SyncRoot
{
get { return syncRoot; }
}
public string[] GetKeys() => dic.Keys.ToArray();//GetKeys()
//{
// return dic.Keys.ToArray();
//}
public Structure Add(string key, object value)
{
if (dic.ContainsKey(key))
dic[key] = value;
else
dic.Add(key, value);
return this;
}
public object this[string index]
{
get
{
if (dic.ContainsKey(index))
return dic[index];
else
return null;
}
set
{
if (dic.ContainsKey(index))
dic[index] = value;
else
dic.Add(index, value);
}
}
}

View File

@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Data;
public enum StructureComparisonResult : byte
{
Null,
Structure,
StructureSameKeys,
StructureSameTypes,
Same
}

View File

@ -0,0 +1,247 @@
using Esiur.Net.IIP;
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Data;
public enum TransmissionTypeIdentifier : byte
{
Null = 0x0,
False = 0x1,
True = 0x2,
NotModified = 0x3,
UInt8 = 0x8,
Int8 = 0x9,
Char8 = 0xA,
Int16 = 0x10,
UInt16 = 0x11,
Char16 = 0x12,
Int32 = 0x18,
UInt32 = 0x19,
Float32 = 0x1A,
Resource = 0x1B,
ResourceLocal = 0x1C,
Int64 = 0x20,
UInt64 = 0x21,
Float64 = 0x22,
DateTime = 0x23,
Int128 = 0x28,
UInt128 = 0x29,
Float128 = 0x2A,
RawData = 0x40,
String = 0x41,
List = 0x42,
ResourceList = 0x43,
RecordList = 0x44,
Map = 0x45,
MapList = 0x46,
//Tuple = 0x47,
Record = 0x80,
TypedList = 0x81,
TypedMap = 0x82,
Tuple = 0x83,
Enum = 0x84,
Constant = 0x85
//TypedResourceList = 0x81,
//TypedRecordList = 0x82,
}
public enum TransmissionTypeClass
{
Fixed = 0,
Dynamic = 1,
Typed = 2
}
public struct TransmissionType
{
public TransmissionTypeIdentifier Identifier;
public int Index;
public TransmissionTypeClass Class;
public uint Offset;
public ulong ContentLength;
public byte Exponent;
public TransmissionType(TransmissionTypeIdentifier identifier, TransmissionTypeClass cls, int index, uint offset, ulong contentLength, byte exponent = 0)
{
Identifier = identifier;
Index = index;
Class = cls;
Offset=offset;
ContentLength = contentLength;
Exponent = exponent;
}
public static byte[] Compose(TransmissionTypeIdentifier identifier, byte[] data)
{
if (data == null || data.Length == 0)
return new byte[] { (byte)identifier };
var cls = (TransmissionTypeClass)((int)identifier >> 6);
if (cls == TransmissionTypeClass.Fixed)
{
return DC.Combine(new byte[] { (byte)identifier }, 0, 1, data, 0, (uint)data.Length);
}
else
{
var len = (ulong)data.LongLength;
if (len == 0)
{
return new byte[1] { (byte) identifier };
}
else if (len <= 0xFF)
{
var rt = new byte[2 + len];
rt[0] = (byte)((byte)identifier | 0x8);
rt[1] = (byte)len;
Buffer.BlockCopy(data, 0, rt, 2, (int)len);
return rt;
}
else if (len <= 0xFF_FF)
{
var rt = new byte[3 + len];
rt[0] = (byte)((byte)identifier | 0x10);
rt[1] = (byte)((len >> 8) & 0xFF);
rt[2] = (byte)(len & 0xFF);
Buffer.BlockCopy(data, 0, rt, 3, (int)len);
return rt;
}
else if (len <= 0xFF_FF_FF)
{
var rt = new byte[4 + len];
rt[0] = (byte)((byte)identifier | 0x18);
rt[1] = (byte)((len >> 16) & 0xFF);
rt[2] = (byte)((len >> 8) & 0xFF);
rt[3] = (byte)(len & 0xFF);
Buffer.BlockCopy(data, 0, rt, 4, (int)len);
return rt;
}
else if (len <= 0xFF_FF_FF_FF)
{
var rt = new byte[5 + len];
rt[0] = (byte)((byte)identifier | 0x20);
rt[1] = (byte)((len >> 24) & 0xFF);
rt[2] = (byte)((len >> 16) & 0xFF);
rt[3] = (byte)((len >> 8) & 0xFF);
rt[4] = (byte)(len & 0xFF);
Buffer.BlockCopy(data, 0, rt, 5, (int)len);
return rt;
}
else if (len <= 0xFF_FF_FF_FF_FF)
{
var rt = new byte[6 + len];
rt[0] = (byte)((byte)identifier | 0x28);
rt[1] = (byte)((len >> 32) & 0xFF);
rt[2] = (byte)((len >> 24) & 0xFF);
rt[3] = (byte)((len >> 16) & 0xFF);
rt[4] = (byte)((len >> 8) & 0xFF);
rt[5] = (byte)(len & 0xFF);
Buffer.BlockCopy(data, 0, rt, 6, (int)len);
return rt;
}
else if (len <= 0xFF_FF_FF_FF_FF_FF)
{
var rt = new byte[7 + len];
rt[0] = (byte)((byte)identifier | 0x30);
rt[1] = (byte)((len >> 40) & 0xFF);
rt[2] = (byte)((len >> 32) & 0xFF);
rt[3] = (byte)((len >> 24) & 0xFF);
rt[4] = (byte)((len >> 16) & 0xFF);
rt[5] = (byte)((len >> 8) & 0xFF);
rt[6] = (byte)(len & 0xFF);
Buffer.BlockCopy(data, 0, rt, 7, (int)len);
return rt;
}
else //if (len <= 0xFF_FF_FF_FF_FF_FF_FF)
{
var rt = new byte[8 + len];
rt[0] = (byte)((byte)identifier | 0x38);
rt[1] = (byte)((len >> 48) & 0xFF);
rt[2] = (byte)((len >> 40) & 0xFF);
rt[3] = (byte)((len >> 32) & 0xFF);
rt[4] = (byte)((len >> 24) & 0xFF);
rt[5] = (byte)((len >> 16) & 0xFF);
rt[6] = (byte)((len >> 8) & 0xFF);
rt[7] = (byte)(len & 0xFF);
Buffer.BlockCopy(data, 0, rt, 8, (int)len);
return rt;
}
//else // if (len <= 0xFF_FF_FF_FF_FF_FF_FF_FF)
//{
// var rt = new byte[9 + len];
// rt[0] = (byte)((byte)identifier | 0x8);
// rt[1] = (byte)((len >> 56) & 0xFF);
// rt[2] = (byte)((len >> 48) & 0xFF);
// rt[3] = (byte)((len >> 40) & 0xFF);
// rt[4] = (byte)((len >> 32) & 0xFF);
// rt[5] = (byte)((len >> 24) & 0xFF);
// rt[6] = (byte)((len >> 16) & 0xFF);
// rt[7] = (byte)((len >> 8) & 0xFF);
// rt[8] = (byte)(len & 0xFF);
// Buffer.BlockCopy(data, 0, rt, 9, (int)len);
// return rt;
//}
// // add length
// int bytes = 1;
//for (var i = 56; i > 0; i -= 8, bytes++)
// if (len <= (0xFF_FF_FF_FF_FF_FF_FF_FF >> i))
// break;
//var rt = new byte[1 + bytes + data.Length];
//rt[0] = (byte)((byte)identifier | (bytes << 3));
//for (var i = 1; i <= bytes; i++)
// rt[i] = data.LongLength >> i * 8;
//Buffer.BlockCopy(data, 0, rt, 1 + bytes, data.Length);
}
}
public static (ulong, TransmissionType?) Parse(byte[] data, uint offset, uint ends)
{
var h = data[offset++];
var cls = (TransmissionTypeClass)(h >> 6);
if (cls == TransmissionTypeClass.Fixed)
{
var exp = (h & 0x38) >> 3;
if (exp == 0)
return (1, new TransmissionType((TransmissionTypeIdentifier)h, cls, h & 0x7, 0, (byte)exp));
ulong cl = (ulong)(1 << (exp -1));
if (ends - offset < cl)
return (ends - offset - (uint)cl, null);
//offset += (uint)cl;
return (1 + cl, new TransmissionType((TransmissionTypeIdentifier)h, cls, h & 0x7, offset, cl, (byte)exp));
}
else
{
ulong cll = (ulong)(h >> 3) & 0x7;
if (ends - offset < cll)
return (ends - offset - (uint)cll, null);
ulong cl = 0;
for (uint i = 0; i < cll; i++)
cl = cl << 8 | data[offset++];
return (1 + cl + cll, new TransmissionType((TransmissionTypeIdentifier)(h & 0xC7), cls, h & 0x7, offset, cl));
}
}
}