mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-06-27 05:23:13 +00:00
2.2
This commit is contained in:
@ -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;
|
||||
//
|
||||
}
|
||||
}
|
||||
|
1687
Esiur/Data/Codec.cs
1687
Esiur/Data/Codec.cs
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
|
554
Esiur/Data/DataDeserializer.cs
Normal file
554
Esiur/Data/DataDeserializer.cs
Normal 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;
|
||||
|
||||
}
|
||||
|
||||
}
|
416
Esiur/Data/DataSerializer.cs
Normal file
416
Esiur/Data/DataSerializer.cs
Normal 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
12
Esiur/Data/Endian.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Data
|
||||
{
|
||||
public enum Endian
|
||||
{
|
||||
Big,
|
||||
Little
|
||||
}
|
||||
}
|
@ -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
248
Esiur/Data/Map.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Data;
|
||||
|
||||
public enum RecordComparisonResult : byte
|
||||
{
|
||||
Null,
|
||||
Record,
|
||||
RecordSameType,
|
||||
Same
|
||||
}
|
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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
247
Esiur/Data/TransmissionType.cs
Normal file
247
Esiur/Data/TransmissionType.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user