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

View File

@ -39,6 +39,11 @@ public class EntityStore : IStore
{
public Instance Instance { get; set; }
bool initialized = false;
public bool Initialized => initialized;
public event DestroyedEvent OnDestroy;
Dictionary<Type, Dictionary<object, WeakReference>> DB = new Dictionary<Type, Dictionary<object, WeakReference>>();
@ -92,6 +97,9 @@ public class EntityStore : IStore
public IResource GetById(Type type, object id)
{
if (!initialized)
throw new Exception("Store not initalized. Make sure the Warehouse is open.");
lock (DBLock)
{
if (!DB[type].ContainsKey(id))
@ -136,13 +144,13 @@ public class EntityStore : IStore
return this.Instance.Name + "/" + type.Name;
}
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
public bool Record(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime)
{
return true;
//throw new NotImplementedException();
}
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
public bool Modify(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime)
{
return true;
//throw new NotImplementedException();
@ -201,6 +209,8 @@ public class EntityStore : IStore
ReloadModel();
initialized = true;
}
return new AsyncReply<bool>(true);

View File

@ -9,7 +9,7 @@
<Product>Esiur Entity Framework Extension</Product>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>Esiur.Stores.EntityCore</PackageId>
<Version>1.2.5</Version>
<Version>1.2.9</Version>
<LangVersion>latest</LangVersion>
</PropertyGroup>
@ -22,7 +22,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
<PackageReference Include="System.Collections" Version="4.3.0" />
</ItemGroup>

View File

@ -54,6 +54,8 @@ public static class EsiurExtensions
{
var store = dbSet.GetInfrastructure().GetService<IDbContextOptions>().FindExtension<EsiurExtensionOptions>().Store;
if (!store.Initialized)
throw new Exception("Store not initialized. Make sure the Warehouse is open");
var manager = store.Instance.Managers.FirstOrDefault();// > 0 ? store.Instance.Managers.First() : null;
@ -75,7 +77,7 @@ public static class EsiurExtensions
else
{
res = Activator.CreateInstance(proxyType) as IResource;
var ps = Structure.FromObject(resource);
var ps = Map<string,object>.FromObject(resource);
foreach (var p in ps)
{

View File

@ -11,7 +11,7 @@
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
<RepositoryUrl>https://github.com/esiur/esiur-dotnet/</RepositoryUrl>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Version>1.5.2</Version>
<Version>1.5.4</Version>
<PackageId>Esiur.Stores.MongoDB</PackageId>
<LangVersion>latest</LangVersion>
</PropertyGroup>

View File

@ -83,7 +83,7 @@ public class MongoDBStore : IStore
}*/
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime date)
public bool Record(IResource resource, string propertyName, object value, ulong? age, DateTime? date)
{
var objectId = resource.Instance.Variables["objectId"].ToString();
//var bsonObjectId = new BsonObjectId(new ObjectId(objectId));
@ -168,7 +168,7 @@ public class MongoDBStore : IStore
var attributes = Parse(document["attributes"]).Then(x =>
{
resource.Instance.SetAttributes(x as Structure);
resource.Instance.SetAttributes(x as Map<string, object>);
});
// var bag = new AsyncBag<object>();
@ -230,10 +230,10 @@ public class MongoDBStore : IStore
else if (doc["type"] == 1)
{
var bag = new AsyncBag<object>();
var rt = new AsyncReply<Structure>();
var rt = new AsyncReply<Map<string, object>>();
var bs = (BsonDocument)doc["values"].AsBsonDocument;
var s = new Structure();
var s = new Map<string, object>();
foreach (var v in bs)
bag.Add(Parse(v.Value));
@ -414,7 +414,7 @@ public class MongoDBStore : IStore
}
}
public BsonDocument ComposeStructure(Structure value)
public BsonDocument ComposeStructure(Map<string, object> value)
{
var rt = new BsonDocument { { "type", 1 } };
@ -436,7 +436,7 @@ public class MongoDBStore : IStore
return rt;
}
BsonArray ComposeStructureArray(Structure[] structures)
BsonArray ComposeStructureArray(Map<string, object>[] structures)
{
var rt = new BsonArray();
@ -466,44 +466,48 @@ public class MongoDBStore : IStore
private BsonValue Compose(object valueObj)
{
var (type, value) = Codec.GetDataType(valueObj, null);
switch (type)
{
case DataType.Void:
// nothing to do;
return BsonNull.Value;
//@TODO : Rewrite
//var (type, value) = Tra Codec.GetDataType(valueObj, null);
case DataType.String:
return new BsonString((string)value);
//switch (type)
//{
// case DataType.Void:
// // nothing to do;
// return BsonNull.Value;
case DataType.Resource:
case DataType.DistributedResource:
// case DataType.String:
// return new BsonString((string)value);
return new BsonDocument { { "type", 0 }, { "link", (value as IResource).Instance.Link } };
// case DataType.Resource:
// case DataType.DistributedResource:
//return new BsonObjectId(new ObjectId((string)(value as IResource).Instance.Variables["objectId"]));
// return new BsonDocument { { "type", 0 }, { "link", (value as IResource).Instance.Link } };
case DataType.Structure:
return ComposeStructure((Structure)value);
// //return new BsonObjectId(new ObjectId((string)(value as IResource).Instance.Variables["objectId"]));
case DataType.VarArray:
return ComposeVarArray((Array)value);
// case DataType.Structure:
// return ComposeStructure((Structure)value);
case DataType.ResourceArray:
if (value is IResource[])
return ComposeResourceArray((IResource[])value);
else
return ComposeResourceArray((IResource[])DC.CastConvert(value, typeof(IResource[])));
// case DataType.VarArray:
// return ComposeVarArray((Array)value);
// case DataType.ResourceArray:
// if (value is IResource[])
// return ComposeResourceArray((IResource[])value);
// else
// return ComposeResourceArray((IResource[])DC.CastConvert(value, typeof(IResource[])));
case DataType.StructureArray:
return ComposeStructureArray((Structure[])value);
// case DataType.StructureArray:
// return ComposeStructureArray((Structure[])value);
default:
return BsonValue.Create(value);
}
// default:
// return BsonValue.Create(value);
//}
return BsonValue.Create(valueObj);
}
public AsyncReply<IResource> Retrieve(uint iid)
@ -776,7 +780,7 @@ public class MongoDBStore : IStore
return reply;
}
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
public bool Modify(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime)
{
if (resource == this)

BIN
Esiur.rar Normal file

Binary file not shown.

View File

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29324.140
# Visual Studio Version 17
VisualStudioVersion = 17.0.31919.166
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esiur", "Esiur\Esiur.csproj", "{4F74A8C1-D38F-4CC0-ACD1-24459BA0EAFC}"
EndProject
@ -8,6 +8,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esiur.Stores.MongoDB", "Esi
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Esiur.Stores.EntityCore", "Esiur.Stores.EntityCore\Esiur.Stores.EntityCore.csproj", "{53DE5A30-CFA9-4DE7-A840-77CFF519D31B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{331F82B6-6B90-4533-9718-F7C8090D8F19}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -26,6 +28,10 @@ Global
{53DE5A30-CFA9-4DE7-A840-77CFF519D31B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53DE5A30-CFA9-4DE7-A840-77CFF519D31B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53DE5A30-CFA9-4DE7-A840-77CFF519D31B}.Release|Any CPU.Build.0 = Release|Any CPU
{331F82B6-6B90-4533-9718-F7C8090D8F19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{331F82B6-6B90-4533-9718-F7C8090D8F19}.Debug|Any CPU.Build.0 = Debug|Any CPU
{331F82B6-6B90-4533-9718-F7C8090D8F19}.Release|Any CPU.ActiveCfg = Release|Any CPU
{331F82B6-6B90-4533-9718-F7C8090D8F19}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -32,7 +32,7 @@ public class AsyncAwaiter<T> : INotifyCompletion
public T GetResult()
{
if (exception != null)
throw exception;
throw exception;
return result;
}

View File

@ -30,37 +30,42 @@ using System.Threading.Tasks;
namespace Esiur.Core;
public class AsyncBag : AsyncReply
interface IAsyncBag
{
public void Add(AsyncReply reply);
}
public class AsyncBag<T> : AsyncReply, IAsyncBag
{
protected List<AsyncReply> replies = new List<AsyncReply>();
List<object> results = new List<object>();
List<T> results = new();
int count = 0;
bool sealedBag = false;
public Type ArrayType { get; set; }
public virtual Type ArrayType { get; set; } = typeof(T);
public AsyncBag Then(Action<object[]> callback)
public AsyncBag<T> Then(Action<T[]> callback)
{
base.Then(new Action<object>(o => callback((object[])o)));
base.Then(new Action<object>(o => callback((T[])o)));
return this;
}
public new AsyncBagAwaiter GetAwaiter()
public new AsyncBagAwaiter<T> GetAwaiter()
{
return new AsyncBagAwaiter(this);
return new AsyncBagAwaiter<T>(this);
}
public new object[] Wait()
public new T[] Wait()
{
return (object[])base.Wait();
return (T[])base.Wait();
}
public new object[] Wait(int timeout)
public new T[] Wait(int timeout)
{
return (object[])base.Wait(timeout);
return (T[])base.Wait(timeout);
}
public void Seal()
@ -71,7 +76,17 @@ public class AsyncBag : AsyncReply
sealedBag = true;
if (results.Count == 0)
Trigger(new object[0]);
{
if (ArrayType != null)
{
var ar = Array.CreateInstance(ArrayType, 0);
Trigger(ar);
}
else
{
Trigger(new object[0]);
}
}
for (var i = 0; i < results.Count; i++)
//foreach(var reply in results.Keys)
@ -81,16 +96,24 @@ public class AsyncBag : AsyncReply
k.Then((r) =>
{
results[index] = r;
results[index] = (T)r;
count++;
if (count == results.Count)
{
if (ArrayType != null)
{
var ar = Array.CreateInstance(ArrayType, count);
for (var i = 0; i < count; i++)
ar.SetValue(results[i], i);
Trigger(ar);
try
{
// @TODO: Safe casting check
var ar = Array.CreateInstance(ArrayType, count);
for (var i = 0; i < count; i++)
ar.SetValue(results[i], i);
Trigger(ar);
}
catch
{
Trigger(results.ToArray());
}
}
else
Trigger(results.ToArray());
@ -103,12 +126,12 @@ public class AsyncBag : AsyncReply
{
if (!sealedBag)
{
results.Add(null);
results.Add(default(T));
replies.Add(reply);
}
}
public void AddBag(AsyncBag bag)
public void AddBag(AsyncBag<T> bag)
{
foreach (var r in bag.replies)
Add(r);
@ -121,10 +144,11 @@ public class AsyncBag : AsyncReply
}
public AsyncBag(object[] results)
public AsyncBag(T[] results)
: base(results)
{
}
}

View File

@ -6,15 +6,15 @@ using System.Threading.Tasks;
namespace Esiur.Core;
public class AsyncBagAwaiter : INotifyCompletion
public class AsyncBagAwaiter<T> : INotifyCompletion
{
Action callback = null;
AsyncException exception = null;
object[] result;
T[] result;
public AsyncBagAwaiter(AsyncBag reply)
public AsyncBagAwaiter(AsyncBag<T> reply)
{
reply.Then(x =>
{
@ -29,7 +29,7 @@ public class AsyncBagAwaiter : INotifyCompletion
});
}
public object[] GetResult()
public T[] GetResult()
{
if (exception != null)
throw exception;

View File

@ -34,10 +34,13 @@ public class AsyncBag<T> : AsyncBag
{
public AsyncBag<T> Then(Action<T[]> callback)
{
base.Then(new Action<object>((o) => callback(((object[])o).Select(x => (T)x).ToArray())));
//base.Then(new Action<object>((o) => callback(((object[])o).Select(x => (T)x).ToArray())));
base.Then(x => callback((T[])x));
return this;
}
public override Type ArrayType => typeof(T);
public void Add(AsyncReply<T> reply)
{
@ -58,9 +61,15 @@ public class AsyncBag<T> : AsyncBag
public new T[] Wait()
{
return base.Wait().Select(x => (T)x).ToArray();
return (T[])base.Wait();// base.Wait().Select(x => (T)x).ToArray();
}
public new T[] Wait(int timeout)
{
return (T[])base.Wait(timeout);
}
public AsyncBag()
{

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

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

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

View File

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

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

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

View File

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

View File

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

View File

@ -0,0 +1,372 @@
using Esiur.Net.IIP;
using Esiur.Resource;
using Esiur.Resource.Template;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Text;
namespace Esiur.Data
{
public enum RepresentationTypeIdentifier
{
Void,
Dynamic,
Bool,
UInt8,
Int8,
Char,
Int16,
UInt16,
Int32,
UInt32,
Float32,
Int64,
UInt64,
Float64,
DateTime,
Int128,
UInt128,
Decimal,
String,
RawData,
Resource,
Record,
List,
Map,
Enum = 0x44,
TypedResource = 0x45, // Followed by UUID
TypedRecord = 0x46, // Followed by UUID
TypedList = 0x48, // Followed by element type
Tuple2 = 0x50, // Followed by element type
TypedMap = 0x51, // Followed by key type and value type
Tuple3 = 0x58,
Tuple4 = 0x60,
Tuple5 = 0x68,
Tuple6 = 0x70,
Tuple7 = 0x78
}
public class RepresentationType
{
public Type? GetRuntimeType()
{
return Identifier switch
{
(RepresentationTypeIdentifier.Void) => typeof(void),
(RepresentationTypeIdentifier.Dynamic) => typeof(object),
(RepresentationTypeIdentifier.Bool) => Nullable ? typeof(bool?) : typeof(bool),
(RepresentationTypeIdentifier.Char) => Nullable ? typeof(char?) : typeof(char),
(RepresentationTypeIdentifier.UInt8) => Nullable ? typeof(byte?) : typeof(byte),
(RepresentationTypeIdentifier.Int8) => Nullable ? typeof(sbyte?) : typeof(sbyte),
(RepresentationTypeIdentifier.Int16) => Nullable ? typeof(short?) : typeof(short),
(RepresentationTypeIdentifier.UInt16) => Nullable ? typeof(ushort?) : typeof(ushort),
(RepresentationTypeIdentifier.Int32) => Nullable ? typeof(int?) : typeof(int),
(RepresentationTypeIdentifier.UInt32) => Nullable ? typeof(uint?) : typeof(uint),
(RepresentationTypeIdentifier.Int64) => Nullable ? typeof(ulong?) : typeof(long),
(RepresentationTypeIdentifier.UInt64) => Nullable ? typeof(ulong?) : typeof(ulong),
(RepresentationTypeIdentifier.Float32) => Nullable ? typeof(float?) : typeof(float),
(RepresentationTypeIdentifier.Float64) => Nullable ? typeof(double?) : typeof(double),
(RepresentationTypeIdentifier.Decimal) => Nullable ? typeof(decimal?) : typeof(decimal),
(RepresentationTypeIdentifier.String) => typeof(string), //Nullable ? typeof(Nullable<string>) : typeof(string),
(RepresentationTypeIdentifier.DateTime) => Nullable ? typeof(DateTime?) : typeof(DateTime),
(RepresentationTypeIdentifier.Resource) => typeof(IResource),
(RepresentationTypeIdentifier.Record) => typeof(IRecord),
(RepresentationTypeIdentifier.TypedRecord) => Warehouse.GetTemplateByClassId((Guid)GUID, TemplateType.Record).DefinedType,
(RepresentationTypeIdentifier.TypedResource) => Warehouse.GetTemplateByClassId((Guid)GUID, TemplateType.Unspecified).DefinedType,
(RepresentationTypeIdentifier.Enum) => Warehouse.GetTemplateByClassId((Guid)GUID, TemplateType.Enum).DefinedType,
_ => null
};
}
public RepresentationTypeIdentifier Identifier;
public bool Nullable;
public Guid? GUID;
//public RepresentationType? SubType1; // List + Map
//public RepresentationType? SubType2; // Map
//public RepresentationType? SubType3; // No types yet
public RepresentationType?[] SubTypes = new RepresentationType[3];
public static RepresentationType? FromType(Type type)
{
var nullType = System.Nullable.GetUnderlyingType(type);
var nullable = false;
if (nullType != null) {
type = nullType;
nullable = true;
}
if (type.IsGenericType)
{
var genericType = type.GetGenericTypeDefinition();
if (genericType == typeof(List<>))
{
var args = type.GetGenericArguments();
if (args[0] == typeof(object))
{
return new RepresentationType(RepresentationTypeIdentifier.List, nullable);
}
else
{
var subType = FromType(args[0]);
if (subType == null) // unrecongnized type
return null;
return new RepresentationType(RepresentationTypeIdentifier.TypedList, nullable, null, subType);
}
}
else if (genericType == typeof(Map<,>))
{
var args = type.GetGenericArguments();
if (args[0] == typeof(object) && args[1] == typeof(object))
{
return new RepresentationType(RepresentationTypeIdentifier.Map, nullable);
}
else
{
var subType1 = FromType(args[0]);
if (subType1 == null)
return null;
var subType2 = FromType(args[1]);
if (subType2 == null)
return null;
return new RepresentationType(RepresentationTypeIdentifier.TypedMap, nullable, null, subType1, subType2);
}
}
else if (genericType == typeof(DistributedPropertyContext<>))
{
var args = type.GetGenericArguments();
return FromType(args[0]);
}
else if (genericType == typeof(ValueTuple<,>))
{
var args = type.GetGenericArguments();
var subTypes = new RepresentationType[args.Length];
for (var i = 0; i < args.Length; i++)
{
subTypes[i] = FromType(args[i]);
if (subTypes[i] == null)
return null;
}
return new RepresentationType(RepresentationTypeIdentifier.Tuple2, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,>))
{
var args = type.GetGenericArguments();
var subTypes = new RepresentationType[args.Length];
for(var i = 0; i < args.Length; i++)
{
subTypes[i] = FromType(args[i]);
if (subTypes[i] == null)
return null;
}
return new RepresentationType(RepresentationTypeIdentifier.Tuple3, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new RepresentationType[args.Length];
for (var i = 0; i < args.Length; i++)
{
subTypes[i] = FromType(args[i]);
if (subTypes[i] == null)
return null;
}
return new RepresentationType(RepresentationTypeIdentifier.Tuple4, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new RepresentationType[args.Length];
for (var i = 0; i < args.Length; i++)
{
subTypes[i] = FromType(args[i]);
if (subTypes[i] == null)
return null;
}
return new RepresentationType(RepresentationTypeIdentifier.Tuple5, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new RepresentationType[args.Length];
for (var i = 0; i < args.Length; i++)
{
subTypes[i] = FromType(args[i]);
if (subTypes[i] == null)
return null;
}
return new RepresentationType(RepresentationTypeIdentifier.Tuple6, nullable, null, subTypes);
}
else if (genericType == typeof(ValueTuple<,,,,,,>))
{
var args = type.GetGenericArguments();
var subTypes = new RepresentationType[args.Length];
for (var i = 0; i < args.Length; i++)
{
subTypes[i] = FromType(args[i]);
if (subTypes[i] == null)
return null;
}
return new RepresentationType(RepresentationTypeIdentifier.Tuple7, nullable, null, subTypes);
}
else
return null;
}
else if (type.IsArray)
{
var elementType = type.GetElementType();
if (elementType == typeof(object))
return new RepresentationType(RepresentationTypeIdentifier.List, nullable);
else
{
var subType = FromType(elementType);
if (subType == null)
return null;
return new RepresentationType(RepresentationTypeIdentifier.TypedList, nullable, null, subType);
}
}
else if (type == typeof(IResource))
return new RepresentationType(RepresentationTypeIdentifier.Resource, nullable);
else if (type == typeof(IRecord) || type == typeof(Record))
return new RepresentationType(RepresentationTypeIdentifier.Record, nullable);
else if (type == typeof(Map<object, object>))
return new RepresentationType(RepresentationTypeIdentifier.Map, nullable);
else if (Codec.ImplementsInterface(type, typeof(IResource)))
{
return new RepresentationType(
RepresentationTypeIdentifier.TypedResource,
nullable,
TypeTemplate.GetTypeGuid(type)
);
}
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
{
return new RepresentationType(
RepresentationTypeIdentifier.TypedRecord,
nullable,
TypeTemplate.GetTypeGuid(type)
);
}
else if (type.IsEnum)
{
return new RepresentationType(RepresentationTypeIdentifier.Enum, nullable, TypeTemplate.GetTypeGuid(type));
}
//else if (typeof(Structure).IsAssignableFrom(t) || t == typeof(ExpandoObject) => RepresentationTypeIdentifier.Structure)
//{
//}
return type switch
{
_ when type == typeof(void) => new RepresentationType(RepresentationTypeIdentifier.Void, nullable),
_ when type == typeof(object) => new RepresentationType(RepresentationTypeIdentifier.Dynamic, nullable),
_ when type == typeof(bool) => new RepresentationType(RepresentationTypeIdentifier.Bool, nullable),
_ when type == typeof(char) => new RepresentationType(RepresentationTypeIdentifier.Char, nullable),
_ when type == typeof(byte) => new RepresentationType(RepresentationTypeIdentifier.UInt8, nullable),
_ when type == typeof(sbyte) => new RepresentationType(RepresentationTypeIdentifier.Int8, nullable),
_ when type == typeof(short) => new RepresentationType(RepresentationTypeIdentifier.Int16, nullable),
_ when type == typeof(ushort) => new RepresentationType(RepresentationTypeIdentifier.UInt16, nullable),
_ when type == typeof(int) => new RepresentationType(RepresentationTypeIdentifier.Int32, nullable),
_ when type == typeof(uint) => new RepresentationType(RepresentationTypeIdentifier.UInt32, nullable),
_ when type == typeof(long) => new RepresentationType(RepresentationTypeIdentifier.Int64, nullable),
_ when type == typeof(ulong) => new RepresentationType(RepresentationTypeIdentifier.UInt64, nullable),
_ when type == typeof(float) => new RepresentationType(RepresentationTypeIdentifier.Float32, nullable),
_ when type == typeof(double) => new RepresentationType(RepresentationTypeIdentifier.Float64, nullable),
_ when type == typeof(decimal) => new RepresentationType(RepresentationTypeIdentifier.Decimal, nullable),
_ when type == typeof(string) => new RepresentationType(RepresentationTypeIdentifier.String, nullable),
_ when type == typeof(DateTime) => new RepresentationType(RepresentationTypeIdentifier.DateTime, nullable),
_ => null
};
}
public RepresentationType(RepresentationTypeIdentifier identifier, bool nullable, Guid? guid = null, params RepresentationType[] subTypes)
{
Nullable = nullable;
Identifier = identifier;
GUID = guid;
SubTypes = subTypes;
}
public byte[] Compose()
{
var rt = new BinaryList();
if (Nullable)
rt.AddUInt8((byte)(0x80 | (byte)Identifier));
else
rt.AddUInt8((byte)Identifier);
if (GUID != null)
rt.AddUInt8Array(DC.ToBytes((Guid)GUID));
if (SubTypes != null)
for (var i = 0; i < SubTypes.Length; i++)
rt.AddUInt8Array(SubTypes[i].Compose());
return rt.ToArray();
}
//public override string ToString() => Identifier.ToString() + (Nullable ? "?" : "")
// + TypeTemplate != null ? "<" + TypeTemplate.ClassName + ">" : "";
public static (uint, RepresentationType) Parse(byte[] data, uint offset)
{
var oOffset = offset;
var header = data[offset++];
bool nullable = (header & 0x80) > 0;
var identifier = (RepresentationTypeIdentifier)(header & 0x7F);
if ((header & 0x40) > 0)
{
var hasGUID = (header & 0x4) > 0;
var subsCount = (header >> 3) & 0x7;
Guid? guid = null;
if (hasGUID)
{
guid = data.GetGuid(offset);
offset += 16;
}
var subs = new RepresentationType[subsCount];
for (var i = 0; i < subsCount; i++)
{
(var len, subs[i]) = RepresentationType.Parse(data, offset);
offset += len;
}
return (offset - oOffset, new RepresentationType(identifier, nullable, guid, subs));
}
else
{
return (1, new RepresentationType(identifier, nullable));
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,12 +6,12 @@
<Copyright>Ahmed Kh. Zamil</Copyright>
<PackageProjectUrl>http://www.esiur.com</PackageProjectUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>2.0.0-alpha</Version>
<Version>2.1.1</Version>
<RepositoryUrl>https://github.com/esiur/esiur-dotnet</RepositoryUrl>
<Authors>Ahmed Kh. Zamil</Authors>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<AssemblyVersion></AssemblyVersion>
<Company>Esiur Foundation</Company>
<FileVersion>2.0.0.0</FileVersion>
<FileVersion></FileVersion>
<AssemblyName>Esiur</AssemblyName>
<RootNamespace>Esiur</RootNamespace>
<PackageId>Esiur</PackageId>
@ -36,11 +36,15 @@
</ItemGroup>
<ItemGroup>
<Compile Remove="Core\AsyncBagAwaiterGeneric.cs" />
<Compile Remove="Core\AsyncBagGeneric.cs" />
<Compile Remove="Core\AsyncReplyNon.cs" />
<Compile Remove="Core\IAsyncReply.cs" />
<Compile Remove="Data\DataType.cs" />
<Compile Remove="Resource\ResourceEvent.cs" />
<Compile Remove="Resource\ResourceFunction.cs" />
<Compile Remove="Resource\ResourceProperty.cs" />
</ItemGroup>
<ItemGroup>
@ -48,29 +52,31 @@
</ItemGroup>
<ItemGroup>
<None Include="Core\AsyncBagAwaiterGeneric.cs" />
<None Include="Core\AsyncReplyNon.cs" />
<None Include="Core\IAsyncReply.cs" />
<None Include="Data\DataType.cs" />
<None Include="Resource\ResourceEvent.cs" />
<None Include="Resource\ResourceFunction.cs" />
<None Include="Resource\ResourceProperty.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.0.1" />
<PackageReference Include="System.Collections" Version="4.3.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.Diagnostics.StackTrace" Version="4.3.0" />
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
<PackageReference Include="System.Interactive.Async" Version="5.0.0" />
<PackageReference Include="System.Interactive.Async" Version="5.1.0" />
<PackageReference Include="System.Net.NameResolution" Version="4.3.0" />
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
<PackageReference Include="System.Net.Security" Version="4.3.2" />
<PackageReference Include="System.Reflection.Emit" Version="4.7.0" />
<PackageReference Include="System.Text.Json" Version="5.0.2" GeneratePathProperty="true" />
<PackageReference Include="System.Text.Json" Version="6.0.1" GeneratePathProperty="true" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
</ItemGroup>
@ -83,9 +89,22 @@
</ItemGroup>
<ItemGroup>
<None Include="Core\AsyncBagGeneric.cs" />
</ItemGroup>
<ItemGroup>
<None Include="LICENSE" Pack="true" PackagePath="">
</None>
</ItemGroup>
<ItemGroup>
<Page Include="Core\AsyncBagAwaiterGeneric.cs" />
<Page Include="Core\AsyncBagGeneric.cs" />
</ItemGroup>
</Project>

View File

@ -43,6 +43,7 @@ public abstract class PacketFilter : IResource
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public abstract bool Execute(Packet packet);
@ -51,4 +52,6 @@ public abstract class PacketFilter : IResource
{
OnDestroy?.Invoke(this);
}
}

View File

@ -61,6 +61,7 @@ public class PacketServer : IResource
}
public event DestroyedEvent OnDestroy;
public event PropertyModifiedEvent PropertyModified;
public void Destroy()
{

View File

@ -103,26 +103,36 @@ public class HTTPConnection : NetworkConnection
public bool Upgrade()
{
if (IsWebsocketRequest())
var ok = Upgrade(Request, Response);
if (ok)
{
WSMode = true;
Send();
}
return ok;
}
public static bool Upgrade(HTTPRequestPacket request, HTTPResponsePacket response)
{
if (IsWebsocketRequest(request))
{
string magicString = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
string ret = Request.Headers["Sec-WebSocket-Key"] + magicString;
string ret = request.Headers["Sec-WebSocket-Key"] + magicString;
// Compute the SHA1 hash
SHA1 sha = SHA1.Create();
byte[] sha1Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(ret));
Response.Headers["Upgrade"] = Request.Headers["Upgrade"];
Response.Headers["Connection"] = Request.Headers["Connection"];// "Upgrade";
Response.Headers["Sec-WebSocket-Accept"] = Convert.ToBase64String(sha1Hash);
response.Headers["Upgrade"] = request.Headers["Upgrade"];
response.Headers["Connection"] = request.Headers["Connection"];// "Upgrade";
response.Headers["Sec-WebSocket-Accept"] = Convert.ToBase64String(sha1Hash);
if (Request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
Response.Headers["Sec-WebSocket-Protocol"] = Request.Headers["Sec-WebSocket-Protocol"];
if (request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
response.Headers["Sec-WebSocket-Protocol"] = request.Headers["Sec-WebSocket-Protocol"];
Response.Number = HTTPResponsePacket.ResponseCode.Switching;
Response.Text = "Switching Protocols";
WSMode = true;
Send();
response.Number = HTTPResponsePacket.ResponseCode.Switching;
response.Text = "Switching Protocols";
return true;
}
@ -212,13 +222,18 @@ public class HTTPConnection : NetworkConnection
public bool IsWebsocketRequest()
{
if (Request.Headers.ContainsKey("connection")
&& Request.Headers["connection"].ToLower().Contains("upgrade")
&& Request.Headers.ContainsKey("upgrade")
&& Request.Headers["upgrade"].ToLower() == "websocket"
&& Request.Headers.ContainsKey("Sec-WebSocket-Version")
&& Request.Headers["Sec-WebSocket-Version"] == "13"
&& Request.Headers.ContainsKey("Sec-WebSocket-Key"))
return IsWebsocketRequest(this.Request);
}
public static bool IsWebsocketRequest(HTTPRequestPacket request)
{
if (request.Headers.ContainsKey("connection")
&& request.Headers["connection"].ToLower().Contains("upgrade")
&& request.Headers.ContainsKey("upgrade")
&& request.Headers["upgrade"].ToLower() == "websocket"
&& request.Headers.ContainsKey("Sec-WebSocket-Version")
&& request.Headers["Sec-WebSocket-Version"] == "13"
&& request.Headers.ContainsKey("Sec-WebSocket-Key"))
//&& Request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
{
return true;
@ -284,7 +299,7 @@ public class HTTPConnection : NetworkConnection
if (IsWebsocketRequest() & !WSMode)
if (IsWebsocketRequest(Request) & !WSMode)
{
Upgrade();
//return;

View File

@ -46,7 +46,6 @@ public abstract class HTTPFilter : IResource
}
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
/*

View File

@ -155,7 +155,12 @@ public class HTTPServer : NetworkServer<HTTPConnection>, IResource
return false;
}
//public delegate void HTTPGetHandler(HTTPConnection connection, object[] params values);
public void MapGet(string pattern, Delegate handler)
{
// if (p)
}
/*

View File

@ -39,6 +39,7 @@ using Esiur.Resource.Template;
using System.Linq;
using System.Diagnostics;
using static Esiur.Net.Packets.IIPPacket;
using Esiur.Net.HTTP;
namespace Esiur.Net.IIP;
public partial class DistributedConnection : NetworkConnection, IStore
@ -56,6 +57,8 @@ public partial class DistributedConnection : NetworkConnection, IStore
/// </summary>
public event ErrorEvent OnError;
IIPPacket packet = new IIPPacket();
IIPAuthPacket authPacket = new IIPAuthPacket();
@ -71,8 +74,12 @@ public partial class DistributedConnection : NetworkConnection, IStore
string _hostname;
ushort _port;
bool initialPacket = true;
DateTime loginDate;
/// <summary>
/// Local username to authenticate ourselves.
/// </summary>
@ -350,7 +357,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
if (ready)
{
var rt = packet.Parse(msg, offset, ends);
//Console.WriteLine("Rec: " + chunkId + " " + packet.ToString());
Console.WriteLine("Rec: " + chunkId + " " + packet.ToString());
/*
if (packet.Command == IIPPacketCommand.Event)
@ -394,10 +401,10 @@ public partial class DistributedConnection : NetworkConnection, IStore
IIPEventResourceDestroyed(packet.ResourceId);
break;
case IIPPacket.IIPPacketEvent.PropertyUpdated:
IIPEventPropertyUpdated(packet.ResourceId, packet.MethodIndex, packet.Content);
IIPEventPropertyUpdated(packet.ResourceId, packet.MethodIndex, (TransmissionType)packet.DataType, msg);// packet.Content);
break;
case IIPPacket.IIPPacketEvent.EventOccurred:
IIPEventEventOccurred(packet.ResourceId, packet.MethodIndex, packet.Content);
IIPEventEventOccurred(packet.ResourceId, packet.MethodIndex, (TransmissionType)packet.DataType, msg);//packet.Content);
break;
case IIPPacketEvent.ChildAdded:
@ -407,10 +414,11 @@ public partial class DistributedConnection : NetworkConnection, IStore
IIPEventChildRemoved(packet.ResourceId, packet.ChildId);
break;
case IIPPacketEvent.Renamed:
IIPEventRenamed(packet.ResourceId, packet.Content);
IIPEventRenamed(packet.ResourceId, packet.ResourceLink);
break;
case IIPPacketEvent.AttributesUpdated:
IIPEventAttributesUpdated(packet.ResourceId, packet.Content);
// @TODO: fix this
//IIPEventAttributesUpdated(packet.ResourceId, packet.Content);
break;
}
}
@ -429,7 +437,8 @@ public partial class DistributedConnection : NetworkConnection, IStore
IIPRequestDetachResource(packet.CallbackId, packet.ResourceId);
break;
case IIPPacket.IIPPacketAction.CreateResource:
IIPRequestCreateResource(packet.CallbackId, packet.StoreId, packet.ResourceId, packet.Content);
//@TODO : fix this
//IIPRequestCreateResource(packet.CallbackId, packet.StoreId, packet.ResourceId, packet.Content);
break;
case IIPPacket.IIPPacketAction.DeleteResource:
IIPRequestDeleteResource(packet.CallbackId, packet.ResourceId);
@ -441,7 +450,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
IIPRequestRemoveChild(packet.CallbackId, packet.ResourceId, packet.ChildId);
break;
case IIPPacketAction.RenameResource:
IIPRequestRenameResource(packet.CallbackId, packet.ResourceId, packet.Content);
IIPRequestRenameResource(packet.CallbackId, packet.ResourceId, packet.ResourceName);
break;
// Inquire
@ -474,13 +483,13 @@ public partial class DistributedConnection : NetworkConnection, IStore
break;
// Invoke
case IIPPacket.IIPPacketAction.InvokeFunctionArrayArguments:
IIPRequestInvokeFunctionArrayArguments(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.Content);
case IIPPacket.IIPPacketAction.InvokeFunction:
IIPRequestInvokeFunction(packet.CallbackId, packet.ResourceId, packet.MethodIndex, (TransmissionType)packet.DataType, msg);
break;
case IIPPacket.IIPPacketAction.InvokeFunctionNamedArguments:
IIPRequestInvokeFunctionNamedArguments(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.Content);
break;
//case IIPPacket.IIPPacketAction.InvokeFunctionNamedArguments:
// IIPRequestInvokeFunctionNamedArguments(packet.CallbackId, packet.ResourceId, packet.MethodIndex, (TransmissionType)packet.DataType, msg);
// break;
//case IIPPacket.IIPPacketAction.GetProperty:
// IIPRequestGetProperty(packet.CallbackId, packet.ResourceId, packet.MethodIndex);
@ -498,27 +507,33 @@ public partial class DistributedConnection : NetworkConnection, IStore
break;
case IIPPacket.IIPPacketAction.SetProperty:
IIPRequestSetProperty(packet.CallbackId, packet.ResourceId, packet.MethodIndex, packet.Content);
IIPRequestSetProperty(packet.CallbackId, packet.ResourceId, packet.MethodIndex, (TransmissionType)packet.DataType, msg);
break;
// Attribute
case IIPPacketAction.GetAllAttributes:
IIPRequestGetAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
// @TODO : fix this
//IIPRequestGetAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
break;
case IIPPacketAction.UpdateAllAttributes:
IIPRequestUpdateAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
// @TODO : fix this
//IIPRequestUpdateAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
break;
case IIPPacketAction.ClearAllAttributes:
IIPRequestClearAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
// @TODO : fix this
//IIPRequestClearAttributes(packet.CallbackId, packet.ResourceId, packet.Content, true);
break;
case IIPPacketAction.GetAttributes:
IIPRequestGetAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
// @TODO : fix this
//IIPRequestGetAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
break;
case IIPPacketAction.UpdateAttributes:
IIPRequestUpdateAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
// @TODO : fix this
//IIPRequestUpdateAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
break;
case IIPPacketAction.ClearAttributes:
IIPRequestClearAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
// @TODO : fix this
//IIPRequestClearAttributes(packet.CallbackId, packet.ResourceId, packet.Content, false);
break;
}
}
@ -528,11 +543,11 @@ public partial class DistributedConnection : NetworkConnection, IStore
{
// Manage
case IIPPacket.IIPPacketAction.AttachResource:
IIPReply(packet.CallbackId, packet.ClassId, packet.ResourceAge, packet.ResourceLink, packet.Content);
IIPReply(packet.CallbackId, packet.ClassId, packet.ResourceAge, packet.ResourceLink, packet.DataType, msg);
break;
case IIPPacket.IIPPacketAction.ReattachResource:
IIPReply(packet.CallbackId, packet.ResourceAge, packet.Content);
IIPReply(packet.CallbackId, packet.ResourceAge, packet.DataType, msg);
break;
case IIPPacket.IIPPacketAction.DetachResource:
@ -555,7 +570,9 @@ public partial class DistributedConnection : NetworkConnection, IStore
case IIPPacket.IIPPacketAction.TemplateFromClassName:
case IIPPacket.IIPPacketAction.TemplateFromClassId:
case IIPPacket.IIPPacketAction.TemplateFromResourceId:
IIPReply(packet.CallbackId, TypeTemplate.Parse(packet.Content));
var content = msg.Clip(packet.DataType.Value.Offset, (uint)packet.DataType.Value.ContentLength);
IIPReply(packet.CallbackId, TypeTemplate.Parse(content));
break;
case IIPPacketAction.QueryLink:
@ -563,13 +580,12 @@ public partial class DistributedConnection : NetworkConnection, IStore
case IIPPacketAction.ResourceParents:
case IIPPacketAction.ResourceHistory:
case IIPPacketAction.LinkTemplates:
IIPReply(packet.CallbackId, packet.Content);
IIPReply(packet.CallbackId, (TransmissionType)packet.DataType, msg);// packet.Content);
break;
// Invoke
case IIPPacket.IIPPacketAction.InvokeFunctionArrayArguments:
case IIPPacket.IIPPacketAction.InvokeFunctionNamedArguments:
IIPReplyInvoke(packet.CallbackId, packet.Content);
case IIPPacket.IIPPacketAction.InvokeFunction:
IIPReplyInvoke(packet.CallbackId, (TransmissionType)packet.DataType, msg);// packet.Content);
break;
//case IIPPacket.IIPPacketAction.GetProperty:
@ -589,7 +605,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
// Attribute
case IIPPacketAction.GetAllAttributes:
case IIPPacketAction.GetAttributes:
IIPReply(packet.CallbackId, packet.Content);
IIPReply(packet.CallbackId, (TransmissionType)packet.DataType, msg);// packet.Content);
break;
case IIPPacketAction.UpdateAllAttributes:
@ -616,7 +632,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
IIPReportProgress(packet.CallbackId, ProgressType.Execution, packet.ProgressValue, packet.ProgressMax);
break;
case IIPPacketReport.ChunkStream:
IIPReportChunk(packet.CallbackId, packet.Content);
IIPReportChunk(packet.CallbackId, (TransmissionType)packet.DataType, msg);// packet.Content);
break;
}
@ -626,6 +642,62 @@ public partial class DistributedConnection : NetworkConnection, IStore
else
{
// check if the reqeust through websockets
if (initialPacket)
{
initialPacket = false;
if (msg.Length > 3 && Encoding.Default.GetString(msg, 0, 3) == "GET")
{
// Parse with http packet
var req = new HTTPRequestPacket();
var pSize = req.Parse(msg, 0, (uint)msg.Length);
if (pSize > 0)
{
// check for WS upgrade
if (HTTPConnection.IsWebsocketRequest(req))
{
Socket?.Unhold();
var res = new HTTPResponsePacket();
HTTPConnection.Upgrade(req, res);
res.Compose(HTTPResponsePacket.ComposeOptions.AllCalculateLength);
Send(res.Data);
// replace my socket with websockets
var tcpSocket = this.Unassign();
var wsSocket = new WSocket(tcpSocket);
this.Assign(wsSocket);
}
else
{
var res = new HTTPResponsePacket();
res.Number = HTTPResponsePacket.ResponseCode.BadRequest;
res.Compose(HTTPResponsePacket.ComposeOptions.AllCalculateLength);
Send(res.Data);
//@TODO: kill the connection
}
}
else
{
// packet incomplete
return (uint)pSize;
}
// switching completed
return (uint)msg.Length;
}
}
Console.WriteLine(msg.GetString(offset, ends - offset));
var rt = authPacket.Parse(msg, offset, ends);
//Console.WriteLine(session.LocalAuthentication.Type.ToString() + " " + offset + " " + ends + " " + rt + " " + authPacket.ToString());
@ -649,7 +721,16 @@ public partial class DistributedConnection : NetworkConnection, IStore
{
try
{
Server.Membership.UserExists(authPacket.RemoteUsername, authPacket.Domain).Then(x =>
if (Server.Membership == null)
{
var errMsg = DC.ToBytes("Membership not set.");
SendParams().AddUInt8(0xc0)
.AddUInt8((byte)ExceptionCode.GeneralFailure)
.AddUInt16((ushort)errMsg.Length)
.AddUInt8Array(errMsg).Done();
}
else Server.Membership.UserExists(authPacket.RemoteUsername, authPacket.Domain).Then(x =>
{
if (x)
{
@ -660,15 +741,15 @@ public partial class DistributedConnection : NetworkConnection, IStore
.AddUInt8(0xa0)
.AddUInt8Array(localNonce)
.Done();
//SendParams((byte)0xa0, localNonce);
}
//SendParams((byte)0xa0, localNonce);
}
else
{
//Console.WriteLine("User not found");
SendParams().AddUInt8(0xc0)
.AddUInt8((byte)ExceptionCode.UserOrTokenNotFound)
.AddUInt16(14)
.AddString("User not found").Done();
//Console.WriteLine("User not found");
SendParams().AddUInt8(0xc0)
.AddUInt8((byte)ExceptionCode.UserOrTokenNotFound)
.AddUInt16(14)
.AddString("User not found").Done();
}
});
}
@ -686,31 +767,43 @@ public partial class DistributedConnection : NetworkConnection, IStore
{
try
{
// Check if user and token exists
Server.Membership.TokenExists(authPacket.RemoteTokenIndex, authPacket.Domain).Then(x =>
if (Server.Membership == null)
{
if (x != null)
{
session.RemoteAuthentication.Username = x;
session.RemoteAuthentication.TokenIndex = authPacket.RemoteTokenIndex;
remoteNonce = authPacket.RemoteNonce;
session.RemoteAuthentication.Domain = authPacket.Domain;
SendParams()
.AddUInt8(0xa0)
.AddUInt8Array(localNonce)
.Done();
}
else
{
//Console.WriteLine("User not found");
SendParams()
SendParams()
.AddUInt8(0xc0)
.AddUInt8((byte)ExceptionCode.UserOrTokenNotFound)
.AddUInt16(15)
.AddString("Token not found")
.Done();
}
});
}
// Check if user and token exists
else
{
Server.Membership.TokenExists(authPacket.RemoteTokenIndex, authPacket.Domain).Then(x =>
{
if (x != null)
{
session.RemoteAuthentication.Username = x;
session.RemoteAuthentication.TokenIndex = authPacket.RemoteTokenIndex;
remoteNonce = authPacket.RemoteNonce;
session.RemoteAuthentication.Domain = authPacket.Domain;
SendParams()
.AddUInt8(0xa0)
.AddUInt8Array(localNonce)
.Done();
}
else
{
//Console.WriteLine("User not found");
SendParams()
.AddUInt8(0xc0)
.AddUInt8((byte)ExceptionCode.UserOrTokenNotFound)
.AddUInt16(15)
.AddString("Token not found")
.Done();
}
});
}
}
catch (Exception ex)
{
@ -729,7 +822,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
try
{
// Check if guests are allowed
if (Server.Membership.GuestsAllowed)
if (Server.Membership?.GuestsAllowed ?? true)
{
session.RemoteAuthentication.Username = "g-" + Global.GenerateCode();
session.RemoteAuthentication.Domain = authPacket.Domain;
@ -789,31 +882,31 @@ public partial class DistributedConnection : NetworkConnection, IStore
if (pw != null)
{
var hashFunc = SHA256.Create();
//var hash = hashFunc.ComputeHash(BinaryList.ToBytes(pw, remoteNonce, localNonce));
var hash = hashFunc.ComputeHash((new BinaryList())
.AddUInt8Array(pw)
.AddUInt8Array(remoteNonce)
.AddUInt8Array(localNonce)
.ToArray());
//var hash = hashFunc.ComputeHash(BinaryList.ToBytes(pw, remoteNonce, localNonce));
var hash = hashFunc.ComputeHash((new BinaryList())
.AddUInt8Array(pw)
.AddUInt8Array(remoteNonce)
.AddUInt8Array(localNonce)
.ToArray());
if (hash.SequenceEqual(remoteHash))
{
// send our hash
//var localHash = hashFunc.ComputeHash(BinaryList.ToBytes(localNonce, remoteNonce, pw));
//SendParams((byte)0, localHash);
// send our hash
//var localHash = hashFunc.ComputeHash(BinaryList.ToBytes(localNonce, remoteNonce, pw));
//SendParams((byte)0, localHash);
var localHash = hashFunc.ComputeHash((new BinaryList()).AddUInt8Array(localNonce).AddUInt8Array(remoteNonce).AddUInt8Array(pw).ToArray());
var localHash = hashFunc.ComputeHash((new BinaryList()).AddUInt8Array(localNonce).AddUInt8Array(remoteNonce).AddUInt8Array(pw).ToArray());
SendParams().AddUInt8(0).AddUInt8Array(localHash).Done();
readyToEstablish = true;
}
else
{
//Global.Log("auth", LogType.Warning, "U:" + RemoteUsername + " IP:" + Socket.RemoteEndPoint.Address.ToString() + " S:DENIED");
SendParams().AddUInt8(0xc0)
.AddUInt8((byte)ExceptionCode.AccessDenied)
.AddUInt16(13)
.AddString("Access Denied")
.Done();
//Global.Log("auth", LogType.Warning, "U:" + RemoteUsername + " IP:" + Socket.RemoteEndPoint.Address.ToString() + " S:DENIED");
SendParams().AddUInt8(0xc0)
.AddUInt8((byte)ExceptionCode.AccessDenied)
.AddUInt16(13)
.AddString("Access Denied")
.Done();
}
}
});
@ -849,7 +942,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
openReply?.Trigger(true);
OnReady?.Invoke(this);
Server?.Membership.Login(session);
Server?.Membership?.Login(session);
loginDate = DateTime.Now;
}).Error(x =>
@ -862,7 +955,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
ready = true;
openReply?.Trigger(true);
OnReady?.Invoke(this);
Server?.Membership.Login(session);
Server?.Membership?.Login(session);
}
//Global.Log("auth", LogType.Warning, "U:" + RemoteUsername + " IP:" + Socket.RemoteEndPoint.Address.ToString() + " S:AUTH");
@ -988,7 +1081,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
protected override void DataReceived(NetworkBuffer data)
{
// Console.WriteLine("DR " + hostType + " " + data.Available + " " + RemoteEndPoint.ToString());
//Console.WriteLine("DR " + data.Available + " " + RemoteEndPoint.ToString());
var msg = data.Read();
uint offset = 0;
uint ends = (uint)msg.Length;
@ -997,7 +1090,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
var chunkId = (new Random()).Next(1000, 1000000);
var list = new List<Structure>();// double, IIPPacketCommand>();
//var list = new List<Map<string, object>>();// double, IIPPacketCommand>();
this.Socket.Hold();
@ -1127,7 +1220,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
{
try
{
var bag = new AsyncBag();
var bag = new AsyncBag<IResource>();
for (var i = 0; i < resources.Keys.Count; i++)
{
@ -1168,13 +1261,13 @@ public partial class DistributedConnection : NetworkConnection, IStore
return new AsyncReply<bool>(true);
}
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
public bool Record(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime)
{
// nothing to do
return true;
}
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
public bool Modify(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime)
{
// nothing to do
return true;
@ -1202,9 +1295,10 @@ public partial class DistributedConnection : NetworkConnection, IStore
throw new NotImplementedException();
}
public AsyncBag<T> Children<T>(IResource resource, string name) where T : IResource
{
throw new Exception("SS");
throw new Exception("Not implemented");
//if (Codec.IsLocalResource(resource, this))
// return new AsyncBag<T>((resource as DistributedResource).children.Where(x => x.GetType() == typeof(T)).Select(x => (T)x));
@ -1214,7 +1308,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
public AsyncBag<T> Parents<T>(IResource resource, string name) where T : IResource
{
throw new Exception("SS");
throw new Exception("Not implemented");
//if (Codec.IsLocalResource(resource, this))
// return (resource as DistributedResource).parents.Where(x => x.GetType() == typeof(T)).Select(x => (T)x);
@ -1253,7 +1347,7 @@ public partial class DistributedConnection : NetworkConnection, IStore
Warehouse.Remove(this);
if (ready)
Server?.Membership.Logout(session);
Server?.Membership?.Logout(session);
ready = false;
}

File diff suppressed because it is too large Load Diff

View File

@ -3,23 +3,34 @@ using System.Collections.Generic;
using System.Text;
namespace Esiur.Net.IIP;
public class DistributedPropertyContext
{
public object Value { get; private set; }
public DistributedConnection Connection { get; private set; }
public Func<DistributedConnection, object> Method { get; private set; }
public DistributedPropertyContext(DistributedConnection connection, object value)
public interface IDistributedPropertyContext
{
object GetValue(DistributedConnection connection);
}
public class DistributedPropertyContext<T> : IDistributedPropertyContext
{
public T Value { get; private set; }
public DistributedConnection Connection { get; private set; }
public Func<DistributedConnection, T> Method { get; private set; }
public DistributedPropertyContext(DistributedConnection connection, T value)
{
this.Value = value;
this.Connection = connection;
}
public DistributedPropertyContext(Func<DistributedConnection, object> method)
public DistributedPropertyContext(Func<DistributedConnection, T> method)
{
this.Method = method;
}
public static implicit operator DistributedPropertyContext(Func<DistributedConnection, object> method)
=> new DistributedPropertyContext(method);
public static implicit operator DistributedPropertyContext<T>(Func<DistributedConnection, T> method)
=> new DistributedPropertyContext<T>(method);
public object GetValue(DistributedConnection connection)
{
return Method.Invoke(connection);
}
}

View File

@ -52,7 +52,8 @@ public class DistributedResource : DynamicObject, IResource
/// Raised when the distributed resource is destroyed.
/// </summary>
public event DestroyedEvent OnDestroy;
public event Instance.ResourceModifiedEvent OnModified;
public event PropertyModifiedEvent PropertyModified;
uint instanceId;
DistributedConnection connection;
@ -83,6 +84,8 @@ public class DistributedResource : DynamicObject, IResource
//}
/// <summary>
/// Connection responsible for the distributed resource.
/// </summary>
@ -214,12 +217,10 @@ public class DistributedResource : DynamicObject, IResource
{
var et = Instance.Template.GetEventTemplateByIndex(index);
events[index]?.Invoke(this, args);
Instance.EmitResourceEvent(et.Name, args);
Instance.EmitResourceEvent(et, args);
}
public AsyncReply<object> _InvokeByNamedArguments(byte index, Structure namedArgs)
public AsyncReply<object> _Invoke(byte index, Map<byte, object> args)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
@ -231,23 +232,7 @@ public class DistributedResource : DynamicObject, IResource
throw new Exception("Function index is incorrect");
return connection.SendInvokeByNamedArguments(instanceId, index, namedArgs);
}
public AsyncReply<object> _InvokeByArrayArguments(byte index, object[] args)
{
if (destroyed)
throw new Exception("Trying to access destroyed object");
if (suspended)
throw new Exception("Trying to access suspended object");
if (index >= Instance.Template.Functions.Length)
throw new Exception("Function index is incorrect");
return connection.SendInvokeByArrayArguments(instanceId, index, args);
return connection.SendInvoke(instanceId, index, args);
}
@ -297,28 +282,40 @@ public class DistributedResource : DynamicObject, IResource
if (attached && ft != null)
{
var indexedArgs = new Map<byte, object>();
if (args.Length == 1)
{
// Detect anonymous types
var type = args[0].GetType();
if (Codec.IsAnonymous(type))
{
var namedArgs = new Structure();
var pi = type.GetTypeInfo().GetProperties();
foreach (var p in pi)
namedArgs[p.Name] = p.GetValue(args[0]);
result = _InvokeByNamedArguments(ft.Index, namedArgs);
var pis = type.GetProperties();
for (byte i = 0; i < ft.Arguments.Length; i++)
{
var pi = pis.FirstOrDefault(x => x.Name == ft.Arguments[i].Name);
if (pi != null)
indexedArgs.Add(i, pi.GetValue(args[0]));
}
result =_Invoke(ft.Index, indexedArgs);
}
else
{
result = _InvokeByArrayArguments(ft.Index, args);
indexedArgs.Add((byte)0, args[0]);
result = _Invoke(ft.Index, indexedArgs);
}
}
else
{
result = _InvokeByArrayArguments(ft.Index, args);
for (byte i = 0; i < args.Length; i++)
indexedArgs.Add(i, args[i]);
result = _Invoke(ft.Index, indexedArgs);
}
return true;
}
@ -341,6 +338,20 @@ public class DistributedResource : DynamicObject, IResource
return properties[index];
}
public bool TryGetPropertyValue(byte index, out object value)
{
if (index >= properties.Length)
{
value = null;
return false;
}
else
{
value = properties[index];
return true;
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (destroyed)
@ -409,6 +420,7 @@ public class DistributedResource : DynamicObject, IResource
return reply;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (destroyed)
@ -496,7 +508,7 @@ public class DistributedResource : DynamicObject, IResource
{
if (trigger == ResourceTrigger.Initialize)
this.Instance.ResourceModified += this.OnModified;
this.Instance.PropertyModified += this.PropertyModified;
// do nothing.
return new AsyncReply<bool>(true);

View File

@ -38,6 +38,9 @@ using Esiur.Security.Membership;
namespace Esiur.Net.IIP;
public class DistributedServer : NetworkServer<DistributedConnection>, IResource
{
[Attribute]
public string IP
{
@ -81,6 +84,8 @@ public class DistributedServer : NetworkServer<DistributedConnection>, IResource
set;
}
public event PropertyModifiedEvent PropertyModified;
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)

View File

@ -170,6 +170,7 @@ public class NetworkBuffer
{
rt = data;
data = new byte[0];
return rt;
}
else
{
@ -200,7 +201,6 @@ public class NetworkBuffer
}
}
return rt;
}
}
}

View File

@ -121,6 +121,8 @@ public abstract class NetworkServer<TConnection> : IDestructible where TConnecti
return;
}
Console.WriteLine("New Socket ... " + DateTime.Now);
var c = new TConnection();
//c.OnClose += ClientDisconnectedEventReceiver;
c.Assign(s);

View File

@ -222,7 +222,7 @@ class IIPAuthPacket : Packet
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var length = data.GetUInt16(offset);
var length = data.GetUInt16(offset, Endian.Little);
offset += 2;
@ -311,7 +311,7 @@ class IIPAuthPacket : Packet
offset += 32;
RemoteTokenIndex = data.GetUInt64(offset);
RemoteTokenIndex = data.GetUInt64(offset, Endian.Little);
offset += 8;
}
}
@ -321,7 +321,7 @@ class IIPAuthPacket : Packet
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var keyLength = data.GetUInt16(offset);
var keyLength = data.GetUInt16(offset, Endian.Little);
offset += 2;
@ -369,7 +369,7 @@ class IIPAuthPacket : Packet
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var keyLength = data.GetUInt16(offset);
var keyLength = data.GetUInt16(offset, Endian.Little);
offset += 2;
@ -394,7 +394,7 @@ class IIPAuthPacket : Packet
ErrorCode = data[offset++];
var cl = data.GetUInt16(offset);
var cl = data.GetUInt16(offset, Endian.Little);
offset += 2;
if (NotEnough(offset, ends, cl))

View File

@ -109,8 +109,8 @@ class IIPPacket : Packet
LinkTemplates,
// Request Invoke
InvokeFunctionArrayArguments = 0x10,
InvokeFunctionNamedArguments,
InvokeFunction = 0x10,
Reserved,
Listen,
Unlisten,
SetProperty,
@ -173,6 +173,7 @@ class IIPPacket : Packet
set;
}
public TransmissionType? DataType { get; set; }
public uint ResourceId { get; set; }
public uint NewResourceId { get; set; }
@ -181,11 +182,13 @@ class IIPPacket : Packet
public uint StoreId { get; set; }
public ulong ResourceAge { get; set; }
public byte[] Content { get; set; }
//public byte[] Content { get; set; }
public ushort ErrorCode { get; set; }
public string ErrorMessage { get; set; }
public string ClassName { get; set; }
public string ResourceLink { get; set; }
public string ResourceName { get; set; }
public Guid ClassId { get; set; }
public byte MethodIndex { get; set; }
public string MethodName { get; set; }
@ -236,7 +239,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
else if (Command == IIPPacketCommand.Report)
@ -246,7 +249,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
CallbackId = data.GetUInt32(offset);
CallbackId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
else
@ -257,7 +260,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
CallbackId = data.GetUInt32(offset);
CallbackId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
@ -268,7 +271,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
NewResourceId = data.GetUInt32(offset);
NewResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
@ -282,7 +285,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
ChildId = data.GetUInt32(offset);
ChildId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
else if (Event == IIPPacketEvent.Renamed)
@ -290,13 +293,15 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var cl = data.GetUInt16(offset);
var cl = data.GetUInt16(offset, Endian.Little);
offset += 2;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
Content = data.Clip(offset, cl);
ResourceName = data.GetString(offset, cl);
//Content = data.Clip(offset, cl);
offset += cl;
}
@ -308,31 +313,19 @@ class IIPPacket : Packet
MethodIndex = data[offset++];
var dt = (DataType)data[offset++];
var size = dt.Size();// Codec.SizeOf(dt);
(var size, DataType) = TransmissionType.Parse(data, offset, ends);
if (size < 0)
{
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
var cl = data.GetUInt32(offset);
offset += 4;
//var dt = (DataType)data[offset++];
//var size = dt.Size();// Codec.SizeOf(dt);
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
if (DataType == null)
return -(int)size;
Content = data.Clip(offset - 5, cl + 5);
offset += cl;
}
else
{
if (NotEnough(offset, ends, (uint)size))
return -dataLengthNeeded;
//Content = data.Clip(DataType.Value.Offset, (uint)DataType.Value.ContentLength);
offset += (uint)size;
Content = data.Clip(offset - 1, (uint)size + 1);
offset += (uint)size;
}
}
//else if (Event == IIPPacketEvent.EventOccurred)
//{
@ -357,13 +350,14 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
var cl = data.GetUInt32(offset);
var cl = data.GetUInt32(offset, Endian.Little);
offset += 4;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
Content = data.Clip(offset, cl);
//@TODO: Fix this
//Content = data.Clip(offset, cl);
offset += cl;
}
@ -375,7 +369,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
else if (Action == IIPPacketAction.ReattachResource)
@ -383,10 +377,10 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 12))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
ResourceAge = data.GetUInt64(offset);
ResourceAge = data.GetUInt64(offset, Endian.Little);
offset += 8;
}
@ -395,7 +389,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
@ -404,25 +398,26 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 12))
return -dataLengthNeeded;
StoreId = data.GetUInt32(offset);
StoreId = data.GetUInt32(offset, Endian.Little);
offset += 4;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
var cl = data.GetUInt32(offset);
var cl = data.GetUInt32(offset, Endian.Little);
offset += 4;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
this.Content = data.Clip(offset, cl);
// @TODO: fix this
//this.Content = data.Clip(offset, cl);
}
else if (Action == IIPPacketAction.DeleteResource)
{
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
@ -432,9 +427,9 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 8))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
ChildId = data.GetUInt32(offset);
ChildId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
else if (Action == IIPPacketAction.RenameResource)
@ -442,15 +437,16 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 6))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
var cl = data.GetUInt16(offset);
var cl = data.GetUInt16(offset, Endian.Little);
offset += 2;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
Content = data.Clip(offset, cl);
ResourceName = data.GetString(offset, cl);
//Content = data.Clip(offset, cl);
offset += cl;
}
else if (Action == IIPPacketAction.TemplateFromClassName)
@ -481,7 +477,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
else if (Action == IIPPacketAction.QueryLink
@ -490,7 +486,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var cl = data.GetUInt16(offset);
var cl = data.GetUInt16(offset, Endian.Little);
offset += 2;
if (NotEnough(offset, ends, cl))
@ -505,7 +501,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
else if (Action == IIPPacketAction.ResourceHistory)
@ -513,35 +509,42 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 20))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
FromDate = data.GetDateTime(offset);
FromDate = data.GetDateTime(offset, Endian.Little);
offset += 8;
ToDate = data.GetDateTime(offset);
ToDate = data.GetDateTime(offset, Endian.Little);
offset += 8;
}
else if (Action == IIPPacketAction.InvokeFunctionArrayArguments
|| Action == IIPPacketAction.InvokeFunctionNamedArguments)
else if (Action == IIPPacketAction.InvokeFunction)
{
if (NotEnough(offset, ends, 9))
if (NotEnough(offset, ends, 6))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
MethodIndex = data[offset++];
var cl = data.GetUInt32(offset);
offset += 4;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
(var size, DataType) = TransmissionType.Parse(data, offset, ends);
Content = data.Clip(offset, cl);
offset += cl;
if (DataType == null)
return -(int)size;
offset += (uint)size;
//var cl = data.GetUInt32(offset);
//offset += 4;
//if (NotEnough(offset, ends, cl))
// return -dataLengthNeeded;
//Content = data.Clip(offset, cl);
//offset += cl;
}
else if (Action == IIPPacketAction.Listen
@ -550,7 +553,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 5))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
MethodIndex = data[offset++];
@ -575,37 +578,21 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 6))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
MethodIndex = data[offset++];
(var size, DataType) = TransmissionType.Parse(data, offset, ends);
var dt = (DataType)data[offset++];
var size = dt.Size();// Codec.SizeOf(dt);
if (DataType == null)
return -(int)size;
if (size < 0)
{
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
var cl = data.GetUInt32(offset);
offset += 4;
//Content = data.Clip(DataType.Value.Offset, (uint)DataType.Value.ContentLength);
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
offset += (uint)size;
Content = data.Clip(offset - 5, cl + 5);
offset += cl;
}
else
{
if (NotEnough(offset, ends, (uint)size))
return -dataLengthNeeded;
Content = data.Clip(offset - 1, (uint)size + 1);
offset += (uint)size;
}
}
// Attributes
else if (Action == IIPPacketAction.UpdateAllAttributes
@ -616,15 +603,16 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 8))
return -dataLengthNeeded;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
var cl = data.GetUInt32(offset);
var cl = data.GetUInt32(offset, Endian.Little);
offset += 4;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
Content = data.Clip(offset, cl);
// @TODO: fix this
//Content = data.Clip(offset, cl);
offset += cl;
}
}
@ -640,10 +628,10 @@ class IIPPacket : Packet
ClassId = data.GetGuid(offset);
offset += 16;
ResourceAge = data.GetUInt64(offset);
ResourceAge = data.GetUInt64(offset, Endian.Little);
offset += 8;
uint cl = data.GetUInt16(offset);
uint cl = data.GetUInt16(offset, Endian.Little);
offset += 2;
if (NotEnough(offset, ends, cl))
@ -652,17 +640,19 @@ class IIPPacket : Packet
ResourceLink = data.GetString(offset, cl);
offset += cl;
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
//if (NotEnough(offset, ends, 4))
// return -dataLengthNeeded;
cl = data.GetUInt32(offset);
offset += 4;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
(var size, DataType) = TransmissionType.Parse(data, offset, ends);
if (DataType == null)
return -(int)size;
offset += (uint)size;
//Content = data.Clip(DataType.Value.Offset, (uint)DataType.Value.ContentLength);
Content = data.Clip(offset, cl);
offset += cl;
}
else if (Action == IIPPacketAction.DetachResource)
{
@ -676,7 +666,7 @@ class IIPPacket : Packet
//ClassId = data.GetGuid(offset);
//offset += 16;
ResourceId = data.GetUInt32(offset);
ResourceId = data.GetUInt32(offset, Endian.Little);
offset += 4;
}
@ -697,51 +687,40 @@ class IIPPacket : Packet
|| Action == IIPPacketAction.GetAllAttributes
|| Action == IIPPacketAction.GetAttributes)
{
if (NotEnough(offset, ends, 4))
if (NotEnough(offset, ends, 1))
return -dataLengthNeeded;
var cl = data.GetUInt32(offset);
offset += 4;
(var size, DataType) = TransmissionType.Parse(data, offset, ends );
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
if (DataType == null)
return -(int)size;
Content = data.Clip(offset, cl);
offset += cl;
offset += (uint)size;
//var cl = data.GetUInt32(offset);
//offset += 4;
//if (NotEnough(offset, ends, cl))
// return -dataLengthNeeded;
//Content = data.Clip(offset, cl);
//offset += cl;
}
else if (Action == IIPPacketAction.InvokeFunctionArrayArguments
|| Action == IIPPacketAction.InvokeFunctionNamedArguments)
else if (Action == IIPPacketAction.InvokeFunction)
//|| Action == IIPPacketAction.GetProperty
//|| Action == IIPPacketAction.GetPropertyIfModified)
{
if (NotEnough(offset, ends, 1))
return -dataLengthNeeded;
var dt = (DataType)data[offset++];
var size = dt.Size();// Codec.SizeOf(dt);
(var size, DataType) = TransmissionType.Parse(data, offset, ends);
if (size < 0)
{
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
if (DataType == null)
return -(int)size;
var cl = data.GetUInt32(offset);
offset += 4;
offset += (uint)size;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
Content = data.Clip(offset - 5, cl + 5);
offset += cl;
}
else
{
if (NotEnough(offset, ends, (uint)size))
return -dataLengthNeeded;
Content = data.Clip(offset - 1, (uint)size + 1);
offset += (uint)size;
}
//Content = data.Clip(DataType.Value.Offset, (uint)DataType.Value.ContentLength);
}
else if (Action == IIPPacketAction.SetProperty
|| Action == IIPPacketAction.Listen
@ -757,7 +736,7 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
ErrorCode = data.GetUInt16(offset);
ErrorCode = data.GetUInt16(offset, Endian.Little);
offset += 2;
}
else if (Report == IIPPacketReport.ExecutionError)
@ -765,13 +744,13 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
ErrorCode = data.GetUInt16(offset);
ErrorCode = data.GetUInt16(offset, Endian.Little);
offset += 2;
if (NotEnough(offset, ends, 2))
return -dataLengthNeeded;
var cl = data.GetUInt16(offset);
var cl = data.GetUInt16(offset, Endian.Little);
offset += 2;
if (NotEnough(offset, ends, cl))
@ -785,9 +764,9 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 8))
return -dataLengthNeeded;
ProgressValue = data.GetInt32(offset);
ProgressValue = data.GetInt32(offset, Endian.Little);
offset += 4;
ProgressMax = data.GetInt32(offset);
ProgressMax = data.GetInt32(offset, Endian.Little);
offset += 4;
}
else if (Report == IIPPacketReport.ChunkStream)
@ -795,31 +774,16 @@ class IIPPacket : Packet
if (NotEnough(offset, ends, 1))
return -dataLengthNeeded;
var dt = (DataType)data[offset++];
var size = dt.Size();// Codec.SizeOf(dt);
if (size < 0)
{
if (NotEnough(offset, ends, 4))
return -dataLengthNeeded;
(var size, DataType) = TransmissionType.Parse(Data, offset, ends );
var cl = data.GetUInt32(offset);
offset += 4;
if (DataType == null)
return -(int)size;
if (NotEnough(offset, ends, cl))
return -dataLengthNeeded;
offset += (uint)size;
Content = data.Clip(offset - 5, cl + 5);
offset += cl;
}
else
{
if (NotEnough(offset, ends, (uint)size))
return -dataLengthNeeded;
//Content = data.Clip(DataType.Value.Offset, (uint)DataType.Value.ContentLength);
Content = data.Clip(offset - 1, (uint)size + 1);
offset += (uint)size;
}
}
}

View File

@ -88,13 +88,13 @@ public class WebsocketPacket : Packet
// 4 bytes
{
pkt.Add((byte)((Mask ? 0x80 : 0x0) | 127));
pkt.AddRange(DC.ToBytes((UInt64)Message.LongCount()));
pkt.AddRange(DC.ToBytes((UInt64)Message.LongCount(), Endian.Big));
}
else if (Message.Length > 125)
// 2 bytes
{
pkt.Add((byte)((Mask ? 0x80 : 0x0) | 126));
pkt.AddRange(DC.ToBytes((UInt16)Message.Length));
pkt.AddRange(DC.ToBytes((UInt16)Message.Length, Endian.Big));
}
else
{
@ -145,7 +145,7 @@ public class WebsocketPacket : Packet
//Console.WriteLine("stage 2 " + needed);
return length - needed;
}
PayloadLength = data.GetUInt16(offset);
PayloadLength = data.GetUInt16(offset, Endian.Big);
offset += 2;
}
else if (PayloadLength == 127)
@ -157,7 +157,7 @@ public class WebsocketPacket : Packet
return length - needed;
}
PayloadLength = data.GetInt64(offset);
PayloadLength = data.GetInt64(offset, Endian.Big);
offset += 8;
}

View File

@ -36,6 +36,7 @@ namespace Esiur.Net.TCP;
public abstract class TCPFilter : IResource
{
public Instance Instance
{
get;
@ -44,6 +45,7 @@ public abstract class TCPFilter : IResource
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
public virtual bool Connected(TCPConnection sender)

View File

@ -66,7 +66,6 @@ public class TCPServer : NetworkServer<TCPConnection>, IResource
TCPFilter[] filters = null;
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
if (trigger == ResourceTrigger.Initialize)

View File

@ -35,6 +35,9 @@ using Esiur.Resource;
namespace Esiur.Net.UDP;
public abstract class UDPFilter : IResource
{
public Instance Instance
{
get;

View File

@ -48,6 +48,7 @@ public class UDPServer : IResource
public event DestroyedEvent OnDestroy;
public Instance Instance
{
get;

View File

@ -74,6 +74,15 @@ public class ResourceGenerator : ISourceGenerator
static string SuggestPropertyName(string propertyName)
{
if (Char.IsUpper(propertyName[0]))
return propertyName.Substring(0, 1).ToLower() + propertyName.Substring(1);
else
return propertyName.Substring(0, 1).ToUpper() + propertyName.Substring(1);
}
public void Execute(GeneratorExecutionContext context)
{
@ -146,27 +155,30 @@ namespace { ci.ClassSymbol.ContainingNamespace.ToDisplayString() } {{
";
if (ci.HasInterface)
code += $"public partial class {ci.Name} {{";
code += $"public partial class {ci.Name} {{\r\n";
else
{
code += @$"public partial class {ci.Name} : IResource {{
public Instance Instance {{ get; set; }}
public event DestroyedEvent OnDestroy;
public virtual void Destroy() {{ OnDestroy?.Invoke(this); }}
code +=
@$" public partial class {ci.Name} : IResource {{
public Instance Instance {{ get; set; }}
public event DestroyedEvent OnDestroy;
public virtual void Destroy() {{ OnDestroy?.Invoke(this); }}
";
if (!ci.HasTrigger)
code += "public AsyncReply<bool> Trigger(ResourceTrigger trigger) => new AsyncReply<bool>(true);\r\n";
code +=
" public AsyncReply<bool> Trigger(ResourceTrigger trigger) => new AsyncReply<bool>(true);\r\n";
}
//Debugger.Launch();
foreach (var f in ci.Fields)
{
var givenName = f.GetAttributes().Where(x => x.AttributeClass.Name == "PublicAttribute").FirstOrDefault()?.ConstructorArguments.FirstOrDefault().Value;
var givenName = f.GetAttributes().Where(x => x.AttributeClass.Name == "PublicAttribute").FirstOrDefault()?.ConstructorArguments.FirstOrDefault().Value as string;
var fn = f.Name;
var pn = givenName ?? fn.Substring(0, 1).ToUpper() + fn.Substring(1);
var pn =string.IsNullOrEmpty(givenName) ? SuggestPropertyName(fn): givenName;
//System.IO.File.AppendAllText("c:\\gen\\fields.txt", fn + " -> " + pn + "\r\n");

View File

@ -29,10 +29,11 @@ public class ResourceGeneratorReceiver : ISyntaxContextReceiver
{
// Debugger.Launch();
var url = import.ConstructorArguments.First().Value.ToString();
var urls = import.ConstructorArguments.Select(x => x.Value.ToString());//.ToString();
if (!Imports.Contains(url))
Imports.Add(url);
foreach(var url in urls)
if (!Imports.Contains(url))
Imports.Add(url);
}
if (attrs.Any(a => a.AttributeClass.ToDisplayString() == "Esiur.Resource.ResourceAttribute"))
@ -48,6 +49,7 @@ public class ResourceGeneratorReceiver : ISyntaxContextReceiver
var fields = cds.Members.Where(x => x is FieldDeclarationSyntax)
.Select(x => context.SemanticModel.GetDeclaredSymbol((x as FieldDeclarationSyntax).Declaration.Variables.First()) as IFieldSymbol)
.Where(x => !x.IsConst)
.Where(x => x.GetAttributes().Any(a => a.AttributeClass.ToDisplayString() == "Esiur.Resource.PublicAttribute"))
.ToArray();

View File

@ -26,7 +26,7 @@ public static class TemplateGenerator
rt.AppendLine("using System;\r\nusing Esiur.Resource;\r\nusing Esiur.Core;\r\nusing Esiur.Data;\r\nusing Esiur.Net.IIP;");
rt.AppendLine($"namespace { nameSpace} {{");
rt.AppendLine($"public class {className} : IRecord {{");
rt.AppendLine($"[Public] public class {className} : IRecord {{");
foreach (var p in template.Properties)
@ -41,58 +41,81 @@ public static class TemplateGenerator
return rt.ToString();
}
static string GetTypeName(TemplateDataType templateDataType, TypeTemplate[] templates)
internal static string GenerateEnum(TypeTemplate template, TypeTemplate[] templates)
{
var cls = template.ClassName.Split('.');
if (templateDataType.Type == DataType.Resource)
return templates.First(x => x.ClassId == templateDataType.TypeGuid && (x.Type == TemplateType.Resource || x.Type == TemplateType.Wrapper)).ClassName;
else if (templateDataType.Type == DataType.ResourceArray)
return templates.First(x => x.ClassId == templateDataType.TypeGuid && (x.Type == TemplateType.Resource || x.Type == TemplateType.Wrapper)).ClassName + "[]";
else if (templateDataType.Type == DataType.Record)
return templates.First(x => x.ClassId == templateDataType.TypeGuid && x.Type == TemplateType.Record).ClassName;
else if (templateDataType.Type == DataType.RecordArray)
return templates.First(x => x.ClassId == templateDataType.TypeGuid && x.Type == TemplateType.Record).ClassName + "[]";
var nameSpace = string.Join(".", cls.Take(cls.Length - 1));
var className = cls.Last();
var name = templateDataType.Type switch
var rt = new StringBuilder();
rt.AppendLine("using System;\r\nusing Esiur.Resource;\r\nusing Esiur.Core;\r\nusing Esiur.Data;\r\nusing Esiur.Net.IIP;");
rt.AppendLine($"namespace { nameSpace} {{");
rt.AppendLine($"[Public] public enum {className} {{");
rt.AppendLine(String.Join(",\r\n", template.Constants.Select(x => $"{x.Name}={x.Value}")));
rt.AppendLine("\r\n}\r\n}");
return rt.ToString();
}
static string GetTypeName(RepresentationType representationType, TypeTemplate[] templates)
{
string name;
if (representationType.Identifier == RepresentationTypeIdentifier.TypedResource)// == DataType.Resource)
name = templates.First(x => x.ClassId == representationType.GUID && (x.Type == TemplateType.Resource || x.Type == TemplateType.Wrapper)).ClassName;
else if (representationType.Identifier == RepresentationTypeIdentifier.TypedRecord)
name = templates.First(x => x.ClassId == representationType.GUID && x.Type == TemplateType.Record).ClassName;
else if (representationType.Identifier == RepresentationTypeIdentifier.Enum)
name = templates.First(x => x.ClassId == representationType.GUID && x.Type == TemplateType.Enum).ClassName;
else if (representationType.Identifier == RepresentationTypeIdentifier.TypedList)
name = GetTypeName(representationType.SubTypes[0], templates) + "[]";
else if (representationType.Identifier == RepresentationTypeIdentifier.TypedMap)
name = "Map<" + GetTypeName(representationType.SubTypes[0], templates)
+ "," + GetTypeName(representationType.SubTypes[1], templates)
+ ">";
else if (representationType.Identifier == RepresentationTypeIdentifier.Tuple2 ||
representationType.Identifier == RepresentationTypeIdentifier.Tuple3 ||
representationType.Identifier == RepresentationTypeIdentifier.Tuple4 ||
representationType.Identifier == RepresentationTypeIdentifier.Tuple5 ||
representationType.Identifier == RepresentationTypeIdentifier.Tuple6 ||
representationType.Identifier == RepresentationTypeIdentifier.Tuple7)
name = "(" + String.Join(",", representationType.SubTypes.Select(x=> GetTypeName(x, templates)))
+ ")";
else
{
DataType.Bool => "bool",
DataType.BoolArray => "bool[]",
DataType.Char => "char",
DataType.CharArray => "char[]",
DataType.DateTime => "DateTime",
DataType.DateTimeArray => "DateTime[]",
DataType.Decimal => "decimal",
DataType.DecimalArray => "decimal[]",
DataType.Float32 => "float",
DataType.Float32Array => "float[]",
DataType.Float64 => "double",
DataType.Float64Array => "double[]",
DataType.Int16 => "short",
DataType.Int16Array => "short[]",
DataType.Int32 => "int",
DataType.Int32Array => "int[]",
DataType.Int64 => "long",
DataType.Int64Array => "long[]",
DataType.Int8 => "sbyte",
DataType.Int8Array => "sbyte[]",
DataType.String => "string",
DataType.StringArray => "string[]",
DataType.Structure => "Structure",
DataType.StructureArray => "Structure[]",
DataType.UInt16 => "ushort",
DataType.UInt16Array => "ushort[]",
DataType.UInt32 => "uint",
DataType.UInt32Array => "uint[]",
DataType.UInt64 => "ulong",
DataType.UInt64Array => "ulong[]",
DataType.UInt8 => "byte",
DataType.UInt8Array => "byte[]",
DataType.VarArray => "object[]",
DataType.Void => "object",
_ => "object"
};
return name;
name = representationType.Identifier switch
{
RepresentationTypeIdentifier.Dynamic => "object",
RepresentationTypeIdentifier.Bool => "bool",
RepresentationTypeIdentifier.Char => "char",
RepresentationTypeIdentifier.DateTime => "DateTime",
RepresentationTypeIdentifier.Decimal => "decimal",
RepresentationTypeIdentifier.Float32 => "float",
RepresentationTypeIdentifier.Float64 => "double",
RepresentationTypeIdentifier.Int16 => "short",
RepresentationTypeIdentifier.Int32 => "int",
RepresentationTypeIdentifier.Int64 => "long",
RepresentationTypeIdentifier.Int8 => "sbyte",
RepresentationTypeIdentifier.String => "string",
RepresentationTypeIdentifier.Map => "Map<object, object>",
RepresentationTypeIdentifier.UInt16 => "ushort",
RepresentationTypeIdentifier.UInt32 => "uint",
RepresentationTypeIdentifier.UInt64 => "ulong",
RepresentationTypeIdentifier.UInt8 => "byte",
RepresentationTypeIdentifier.List => "object[]",
RepresentationTypeIdentifier.Resource => "IResource",
RepresentationTypeIdentifier.Record => "IRecord",
_ => "object"
};
}
return (representationType.Nullable) ? name + "?" : name;
}
public static string GetTemplate(string url, string dir = null, string username = null, string password = null)
@ -142,16 +165,27 @@ public static class TemplateGenerator
var source = GenerateRecord(tmp, templates);
File.WriteAllText(tempDir.FullName + Path.DirectorySeparatorChar + tmp.ClassName + ".Generated.cs", source);
}
else if (tmp.Type == TemplateType.Enum)
{
var source = GenerateEnum(tmp, templates);
File.WriteAllText(tempDir.FullName + Path.DirectorySeparatorChar + tmp.ClassName + ".Generated.cs", source);
}
}
// generate info class
var typesFile = "using System; \r\n namespace Esiur { public static class Generated { public static Type[] Resources {get;} = new Type[] { " +
var typesFile = @"using System;
namespace Esiur {
public static class Generated {
public static Type[] Resources {get;} = new Type[] { " +
string.Join(",", templates.Where(x => x.Type == TemplateType.Resource).Select(x => $"typeof({x.ClassName})"))
+ " }; \r\n public static Type[] Records { get; } = new Type[] { " +
+ @" };
public static Type[] Records { get; } = new Type[] { " +
string.Join(",", templates.Where(x => x.Type == TemplateType.Record).Select(x => $"typeof({x.ClassName})"))
+ " }; " +
+ @" };
public static Type[] Enums { get; } = new Type[] { " +
string.Join(",", templates.Where(x => x.Type == TemplateType.Enum).Select(x => $"typeof({x.ClassName})"))
+ @" };" +
"\r\n } \r\n}";
@ -163,7 +197,6 @@ public static class TemplateGenerator
}
catch (Exception ex)
{
//File.WriteAllText("C:\\gen\\gettemplate.err", ex.ToString());
throw ex;
}
}
@ -179,13 +212,22 @@ public static class TemplateGenerator
rt.AppendLine("using System;\r\nusing Esiur.Resource;\r\nusing Esiur.Core;\r\nusing Esiur.Data;\r\nusing Esiur.Net.IIP;");
rt.AppendLine($"namespace { nameSpace} {{");
rt.AppendLine($"public class {className} : DistributedResource {{");
// extends
if (template.ParentId == null)
rt.AppendLine($"public class {className} : DistributedResource {{");
else
rt.AppendLine($"public class {className} : {templates.First(x => x.ClassId == template.ParentId && x.Type == TemplateType.Resource).ClassName} {{");
rt.AppendLine($"public {className}(DistributedConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) {{}}");
rt.AppendLine($"public {className}() {{}}");
foreach (var f in template.Functions)
{
if (f.Inherited)
continue;
var rtTypeName = GetTypeName(f.ReturnType, templates);
rt.Append($"public AsyncReply<{rtTypeName}> {f.Name}(");
rt.Append(string.Join(",", f.Arguments.Select(x => GetTypeName(x.Type, templates) + " " + x.Name)));
@ -201,6 +243,9 @@ public static class TemplateGenerator
foreach (var p in template.Properties)
{
if (p.Inherited)
continue;
var ptTypeName = GetTypeName(p.ValueType, templates);
rt.AppendLine($"public {ptTypeName} {p.Name} {{");
rt.AppendLine($"get => ({ptTypeName})properties[{p.Index}];");
@ -208,8 +253,19 @@ public static class TemplateGenerator
rt.AppendLine("}");
}
foreach (var c in template.Constants)
{
if (c.Inherited)
continue;
var ctTypeName = GetTypeName(c.ValueType, templates);
rt.AppendLine($"public const {ctTypeName} {c.Name} = {c.Value};");
}
if (template.Events.Length > 0)
{
rt.AppendLine("protected override void _EmitEventByIndex(byte index, object args) {");
rt.AppendLine("switch (index) {");

View File

@ -0,0 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Resource;
public delegate void CustomEventOccurredEvent(CustomEventOccurredInfo info);

View File

@ -0,0 +1,27 @@
using Esiur.Resource.Template;
using Esiur.Security.Authority;
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Resource;
public class CustomEventOccurredInfo
{
public readonly EventTemplate EventTemplate;
public readonly IResource Resource;
public readonly object Value;
public readonly object Issuer;
public readonly Func<Session, bool> Receivers;
public string Name => EventTemplate.Name;
public CustomEventOccurredInfo(IResource resource, EventTemplate eventTemplate, Func<Session, bool> receivers, object issuer, object value)
{
Resource = resource;
EventTemplate = eventTemplate;
Receivers = receivers;
Issuer = issuer;
Value = value;
}
}

View File

@ -0,0 +1,8 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Resource
{
public delegate void EventOccurredEvent(EventOccurredInfo info);
}

View File

@ -0,0 +1,26 @@
using Esiur.Resource.Template;
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Resource
{
public class EventOccurredInfo
{
public readonly EventTemplate EventTemplate;
public string Name => EventTemplate.Name;
public readonly IResource Resource;
public readonly object Value;
public EventOccurredInfo(IResource resource, EventTemplate eventTemplate, object value)
{
Resource = resource;
Value = value;
EventTemplate = eventTemplate;
}
}
}

View File

@ -40,7 +40,6 @@ public delegate bool QueryFilter<T>(T value);
public interface IResource : IDestructible///, INotifyPropertyChanged
{
AsyncReply<bool> Trigger(ResourceTrigger trigger);
[NotMapped]

View File

@ -40,8 +40,8 @@ public interface IStore : IResource
//AsyncReply<IResource> Retrieve(uint iid);
AsyncReply<bool> Put(IResource resource);
string Link(IResource resource);
bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime);
bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime);
bool Record(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime);
bool Modify(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime);
bool Remove(IResource resource);
//bool RemoveAttributes(IResource resource, string[] attributes = null);

View File

@ -7,7 +7,7 @@ namespace Esiur.Resource;
[AttributeUsage(AttributeTargets.Class)]
public class ImportAttribute : Attribute
{
public ImportAttribute(string url)
public ImportAttribute(params string[] urls)
{
}

View File

@ -32,24 +32,20 @@ public class Instance
AutoList<IPermissionsManager, Instance> managers;
public delegate void ResourceModifiedEvent(IResource resource, string propertyName, object newValue);
public delegate void ResourceEventOccurredEvent(IResource resource, string eventName, object args);
public event PropertyModifiedEvent PropertyModified;
public delegate void CustomResourceEventOccurredEvent(IResource resource, object issuer, Func<Session, bool> receivers, string eventName, object args);
public delegate void ResourceDestroyedEvent(IResource resource);
public event ResourceModifiedEvent ResourceModified;
public event ResourceEventOccurredEvent ResourceEventOccurred;
public event CustomResourceEventOccurredEvent CustomResourceEventOccurred;
public event ResourceDestroyedEvent ResourceDestroyed;
public event EventOccurredEvent EventOccurred;
public event CustomEventOccurredEvent CustomEventOccurred;
public event ResourceDestroyedEvent Destroyed;
bool loading = false;
//KeyList<string, object> attributes;
List<ulong> ages = new List<ulong>();
List<DateTime> modificationDates = new List<DateTime>();
List<ulong?> ages = new();
List<DateTime?> modificationDates = new ();
private ulong instanceAge;
private DateTime instanceModificationDate;
@ -100,10 +96,10 @@ public class Instance
*/
}
public Structure GetAttributes(string[] attributes = null)
public Map<string,object> GetAttributes(string[] attributes = null)
{
// @TODO
Structure rt = new Structure();
var rt = new Map<string,object>();
if (attributes != null)
{
@ -172,7 +168,7 @@ public class Instance
*/
}
public bool SetAttributes(Structure attributes, bool clearAttributes = false)
public bool SetAttributes(Map<string,object> attributes, bool clearAttributes = false)
{
// @ TODO
@ -274,7 +270,7 @@ public class Instance
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <returns>Age.</returns>
public ulong GetAge(byte index)
public ulong? GetAge(byte index)
{
if (index < ages.Count)
return ages[index];
@ -287,13 +283,13 @@ public class Instance
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Age.</param>
public void SetAge(byte index, ulong value)
public void SetAge(byte index, ulong? value)
{
if (index < ages.Count)
{
ages[index] = value;
if (value > instanceAge)
instanceAge = value;
instanceAge = (ulong)value;
}
}
@ -302,13 +298,13 @@ public class Instance
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Modification date.</param>
public void SetModificationDate(byte index, DateTime value)
public void SetModificationDate(byte index, DateTime? value)
{
if (index < modificationDates.Count)
{
modificationDates[index] = value;
if (value > instanceModificationDate)
instanceModificationDate = value;
instanceModificationDate = (DateTime) value;
}
}
@ -317,7 +313,7 @@ public class Instance
/// </summary>
/// <param name="index">Zero-based property index</param>
/// <returns>Modification date.</returns>
public DateTime GetModificationDate(byte index)
public DateTime? GetModificationDate(byte index)
{
if (index < modificationDates.Count)
return modificationDates[index];
@ -333,7 +329,7 @@ public class Instance
/// <param name="age">Property age</param>
/// <param name="value">Property value</param>
/// <returns></returns>
public bool LoadProperty(string name, ulong age, DateTime modificationDate, object value)
public bool LoadProperty(string name, ulong? age, DateTime? modificationDate, object value)
{
IResource res;
@ -354,7 +350,8 @@ public class Instance
#endif
*/
if (pt.PropertyInfo.PropertyType == typeof(DistributedPropertyContext))
if (pt.PropertyInfo.PropertyType.IsGenericType
&& pt.PropertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(DistributedPropertyContext<>))
return false;
@ -394,7 +391,7 @@ public class Instance
/// <summary>
/// Last modification date.
/// </summary>
public DateTime ModificationDate
public DateTime? ModificationDate
{
get
{
@ -559,14 +556,15 @@ public class Instance
if (pt.Recordable)
{
store.Record(res, pt.Name, value, ages[pt.Index], now);
}
else //if (pt.Storage == StorageMode.Recordable)
{
store.Modify(res, pt.Name, value, ages[pt.Index], now);
}
ResourceModified?.Invoke(res, pt.Name, value);
//ResourceModified?.Invoke(res, pt.Name, value);
PropertyModified?.Invoke(new PropertyModificationInfo(res, pt, value, instanceAge));
}
}
@ -591,21 +589,21 @@ public class Instance
// internal void EmitResourceEvent(string name, string[] users, DistributedConnection[] connections, object[] args)
internal void EmitCustomResourceEvent(object issuer, Func<Session, bool> receivers, string name, object args)
internal void EmitCustomResourceEvent(object issuer, Func<Session, bool> receivers, EventTemplate eventTemplate, object value)
{
IResource res;
if (this.resource.TryGetTarget(out res))
{
CustomResourceEventOccurred?.Invoke(res, issuer, receivers, name, args);
CustomEventOccurred?.Invoke(new CustomEventOccurredInfo(res, eventTemplate, receivers, issuer, value));
}
}
internal void EmitResourceEvent(string name, object args)
internal void EmitResourceEvent(EventTemplate eventTemplate, object value)
{
IResource res;
if (this.resource.TryGetTarget(out res))
{
ResourceEventOccurred?.Invoke(res, name, args);
EventOccurred?.Invoke(new EventOccurredInfo(res, eventTemplate, value));
}
}
@ -912,7 +910,7 @@ public class Instance
// if (ca.Length == 0)
// continue;
ResourceEventHandler<object> proxyDelegate = (args) => EmitResourceEvent(evt.Name, args);
ResourceEventHandler<object> proxyDelegate = (args) => EmitResourceEvent(evt, args);
evt.EventInfo.AddEventHandler(resource, proxyDelegate);
}
@ -922,7 +920,7 @@ public class Instance
//if (ca.Length == 0)
// continue;
CustomResourceEventHandler<object> proxyDelegate = (issuer, receivers, args) => EmitCustomResourceEvent(issuer, receivers, evt.Name, args);
CustomResourceEventHandler<object> proxyDelegate = (issuer, receivers, args) => EmitCustomResourceEvent(issuer, receivers, evt, args);
evt.EventInfo.AddEventHandler(resource, proxyDelegate);
}
@ -991,6 +989,6 @@ public class Instance
private void Resource_OnDestroy(object sender)
{
ResourceDestroyed?.Invoke((IResource)sender);
Destroyed?.Invoke((IResource)sender);
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;
using Esiur.Resource;
using Esiur.Resource.Template;
namespace Esiur.Resource;
public struct PropertyModificationInfo
{
public readonly IResource Resource;
public readonly PropertyTemplate PropertyTemplate;
public string Name => PropertyTemplate.Name;
public readonly ulong Age;
public object Value;
public PropertyModificationInfo(IResource resource, PropertyTemplate propertyTemplate, object value, ulong age)
{
Resource = resource;
PropertyTemplate = propertyTemplate;
Age = age;
Value = value;
}
}

View File

@ -0,0 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Resource;
public delegate void PropertyModifiedEvent(PropertyModificationInfo data);

View File

@ -4,7 +4,7 @@ using System.Text;
namespace Esiur.Resource;
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Event | AttributeTargets.Class)]
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Event | AttributeTargets.Class | AttributeTargets.Enum)]
public class PublicAttribute : Attribute
{

View File

@ -52,6 +52,7 @@ public class Resource : IResource
return true;
}
~Resource()
{
Destroy();

View File

@ -0,0 +1,8 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Resource
{
public delegate void ResourceDestroyedEvent(IResource resource);
}

View File

@ -34,42 +34,21 @@ namespace Esiur.Resource;
[AttributeUsage(AttributeTargets.Property)]
public class ResourceProperty : System.Attribute
{
bool serialize;
string readExpansion;
string writeExpansion;
// bool recordable;
//bool storable;
//public bool Recordable => recordable;
//public bool Storable => storable;
StorageMode storage;
public readonly bool Nullable;
public readonly StorageMode Storage;
public readonly bool Serialize;
public readonly string ReadExpansion;
public readonly string WriteExpansion;
public StorageMode Storage => storage;
public bool Serialize => serialize;
public string ReadExpansion
public ResourceProperty(StorageMode storage = StorageMode.NonVolatile, bool serialize = true,
string readExpansion = null, string writeExpansion = null)
{
get
{
return readExpansion;
}
}
public string WriteExpansion
{
get
{
return writeExpansion;
}
}
public ResourceProperty(StorageMode storage = StorageMode.NonVolatile, bool serialize = true, string readExpansion = null, string writeExpansion = null)
{
this.readExpansion = readExpansion;
this.writeExpansion = writeExpansion;
this.storage = storage;
this.serialize = serialize;
this.ReadExpansion = readExpansion;
this.WriteExpansion = writeExpansion;
this.Storage = storage;
this.Serialize = serialize;
}
}

View File

@ -40,11 +40,11 @@ public class Storable : global::System.Attribute
SerializerFunction serializer;
DeserializerFunction deserializer;
DataType type;
RepresentationType dataType;
public Storable()
{
type = DataType.Void;
//dataType = = DataType.Void;
}
public DeserializerFunction Deserializer
@ -57,14 +57,14 @@ public class Storable : global::System.Attribute
get { return serializer; }
}
public Storable(DataType type)
public Storable(RepresentationType type)
{
this.type = type;
this.dataType = type;
}
public Storable(DataType type, SerializerFunction serializer, DeserializerFunction deserializer)
public Storable(RepresentationType type, SerializerFunction serializer, DeserializerFunction deserializer)
{
this.type = type;
this.dataType = type;
this.serializer = serializer;
this.deserializer = deserializer;
}

View File

@ -12,6 +12,7 @@ public abstract class Store<T> : IStore where T : IResource
public event DestroyedEvent OnDestroy;
public abstract AsyncReply<bool> AddChild(IResource parent, IResource child);
public abstract AsyncReply<bool> AddParent(IResource child, IResource parent);
@ -30,13 +31,13 @@ public abstract class Store<T> : IStore where T : IResource
public abstract string Link(IResource resource);
public abstract bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime);
public abstract bool Modify(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime);
public abstract AsyncBag<T1> Parents<T1>(IResource resource, string name) where T1 : IResource;
public abstract AsyncReply<bool> Put(IResource resource);
public abstract bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime);
public abstract bool Record(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime);
public abstract bool Remove(IResource resource);

View File

@ -9,18 +9,24 @@ public class ArgumentTemplate
{
public string Name { get; set; }
public TemplateDataType Type { get; set; }
public bool Optional { get; set; }
public RepresentationType Type { get; set; }
public ParameterInfo ParameterInfo { get; set; }
public static (uint, ArgumentTemplate) Parse(byte[] data, uint offset)
public int Index { get; set; }
public static (uint, ArgumentTemplate) Parse(byte[] data, uint offset, int index)
{
var optional = (data[offset++] & 0x1) == 0x1;
var cs = (uint)data[offset++];
var name = data.GetString(offset, cs);
offset += cs;
var (size, type) = TemplateDataType.Parse(data, offset);
var (size, type) = RepresentationType.Parse(data, offset);
return (cs + 1 + size, new ArgumentTemplate(name, type));
return (cs + 2 + size, new ArgumentTemplate(name, index, type, optional));
}
public ArgumentTemplate()
@ -28,10 +34,12 @@ public class ArgumentTemplate
}
public ArgumentTemplate(string name, TemplateDataType type)
public ArgumentTemplate(string name, int index, RepresentationType type, bool optional)
{
Name = name;
Index = index;
Type = type;
Optional = optional;
}
public byte[] Compose()
@ -39,6 +47,7 @@ public class ArgumentTemplate
var name = DC.ToBytes(Name);
return new BinaryList()
.AddUInt8(Optional ? (byte)1 : (byte)0)
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(Type.Compose())

View File

@ -16,8 +16,8 @@ public class AttributeTemplate : MemberTemplate
}
public AttributeTemplate(TypeTemplate template, byte index, string name)
: base(template, MemberType.Attribute, index, name)
public AttributeTemplate(TypeTemplate template, byte index, string name, bool inherited)
: base(template, index, name, inherited)
{
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Text;
using Esiur.Data;
namespace Esiur.Resource.Template;
public class ConstantTemplate : MemberTemplate
{
public readonly object Value;
//public readonly byte[] ValueData;
public readonly string Expansion;
public readonly RepresentationType ValueType;
public ConstantTemplate(TypeTemplate template, byte index, string name, bool inherited, RepresentationType valueType, object value, string expansion)
: base(template, index, name, inherited)
{
Expansion = expansion;
ValueType = valueType;
Value = value;
//try
//{
// Codec.Compose(value, null);
// Value = value;
//}
//catch
//{
// throw new Exception($"Constant `{template.ClassName}.{name}` can't be serialized.");
//}
}
public override byte[] Compose()
{
var name = base.Compose();
var hdr = Inherited ? (byte)0x80 : (byte)0;
if (Expansion != null)
{
var exp = DC.ToBytes(Expansion);
hdr |= 0x70;
return new BinaryList()
.AddUInt8(hdr)
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(ValueType.Compose())
.AddUInt8Array(Codec.Compose(Value, null))
.AddInt32(exp.Length)
.AddUInt8Array(exp)
.ToArray();
}
else
{
hdr |= 0x60;
return new BinaryList()
.AddUInt8(hdr)
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(ValueType.Compose())
.AddUInt8Array(Codec.Compose(Value, null))
.ToArray();
}
}
}

View File

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Resource.Template
{
internal class CustomEventOccurredEvent
{
}
}

View File

@ -19,17 +19,23 @@ public class EventTemplate : MemberTemplate
public EventInfo EventInfo { get; set; }
public TemplateDataType ArgumentType { get; set; }
public RepresentationType ArgumentType { get; set; }
public override byte[] Compose()
{
var name = base.Compose();
var hdr = Inherited ? (byte)0x80 : (byte)0;
if (Listenable)
hdr |= 0x8;
if (Expansion != null)
{
var exp = DC.ToBytes(Expansion);
hdr |= 0x50;
return new BinaryList()
.AddUInt8(Listenable ? (byte)0x58 : (byte)0x50)
.AddUInt8(hdr)
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(ArgumentType.Compose())
@ -38,17 +44,17 @@ public class EventTemplate : MemberTemplate
.ToArray();
}
else
hdr |= 0x40;
return new BinaryList()
.AddUInt8(Listenable ? (byte)0x48 : (byte)0x40)
.AddUInt8(hdr)
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(ArgumentType.Compose())
.ToArray();
}
public EventTemplate(TypeTemplate template, byte index, string name, TemplateDataType argumentType, string expansion = null, bool listenable = false)
: base(template, MemberType.Property, index, name)
public EventTemplate(TypeTemplate template, byte index, string name,bool inherited, RepresentationType argumentType, string expansion = null, bool listenable = false)
: base(template, index, name, inherited)
{
this.Expansion = expansion;
this.Listenable = listenable;

View File

@ -22,7 +22,7 @@ public class FunctionTemplate : MemberTemplate
// set;
//}
public TemplateDataType ReturnType { get; set; }
public RepresentationType ReturnType { get; set; }
public ArgumentTemplate[] Arguments { get; set; }
@ -54,17 +54,16 @@ public class FunctionTemplate : MemberTemplate
var exp = DC.ToBytes(Expansion);
bl.AddInt32(exp.Length)
.AddUInt8Array(exp);
bl.InsertUInt8(0, 0x10);
bl.InsertUInt8(0, Inherited ? (byte)0x90 : (byte)0x10);
}
else
bl.InsertUInt8(0, 0x0);
bl.InsertUInt8(0, Inherited ? (byte)0x80 : (byte)0x0);
return bl.ToArray();
}
public FunctionTemplate(TypeTemplate template, byte index, string name, ArgumentTemplate[] arguments, TemplateDataType returnType, string expansion = null)
: base(template, MemberType.Property, index, name)
public FunctionTemplate(TypeTemplate template, byte index, string name, bool inherited, ArgumentTemplate[] arguments, RepresentationType returnType, string expansion = null)
: base(template, index, name, inherited)
{
//this.IsVoid = isVoid;
this.Arguments = arguments;

View File

@ -8,34 +8,21 @@ using System.Threading.Tasks;
namespace Esiur.Resource.Template;
public class MemberTemplate
{
public enum MemberType
public readonly byte Index;
public readonly string Name;
public readonly bool Inherited;
public readonly TypeTemplate Template;
public MemberTemplate(TypeTemplate template, byte index, string name, bool inherited)
{
Function = 0,
Property = 1,
Event = 2,
Attribute = 3
Template = template;
Index = index;
Name = name;
Inherited = inherited;
}
public byte Index => index;
public string Name => name;
public MemberType Type => type;
TypeTemplate template;
string name;
MemberType type;
byte index;
public TypeTemplate Template => template;
public MemberTemplate(TypeTemplate template, MemberType type, byte index, string name)
{
this.template = template;
this.type = type;
this.index = index;
this.name = name;
}
public string Fullname => template.ClassName + "." + Name;
public string Fullname => Template.ClassName + "." + Name;
public virtual byte[] Compose()
{

View File

@ -23,7 +23,7 @@ public class PropertyTemplate : MemberTemplate
set;
}
public TemplateDataType ValueType { get; set; }
public RepresentationType ValueType { get; set; }
/*
@ -40,6 +40,7 @@ public class PropertyTemplate : MemberTemplate
set;
}
public bool IsNullable { get; set; }
public bool Recordable
{
@ -79,6 +80,9 @@ public class PropertyTemplate : MemberTemplate
var name = base.Compose();
var pv = ((byte)(Permission) << 1) | (Recordable ? 1 : 0);
if (Inherited)
pv |= 0x80;
if (WriteExpansion != null && ReadExpansion != null)
{
var rexp = DC.ToBytes(ReadExpansion);
@ -129,12 +133,14 @@ public class PropertyTemplate : MemberTemplate
}
}
public PropertyTemplate(TypeTemplate template, byte index, string name, TemplateDataType valueType, string read = null, string write = null, bool recordable = false)
: base(template, MemberType.Property, index, name)
public PropertyTemplate(TypeTemplate template, byte index, string name, bool inherited,
RepresentationType valueType, string read = null, string write = null, bool recordable = false)
: base(template, index, name, inherited)
{
this.Recordable = recordable;
//this.Storage = storage;
this.ReadExpansion = read;
if (read != null)
this.ReadExpansion = read;
this.WriteExpansion = write;
this.ValueType = valueType;
}

View File

@ -1,107 +1,131 @@
using Esiur.Data;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Text;
//using Esiur.Data;
//using System;
//using System.Collections;
//using System.Collections.Generic;
//using System.Dynamic;
//using System.Linq;
//using System.Text;
namespace Esiur.Resource.Template;
public struct TemplateDataType
{
public DataType Type { get; set; }
//public string TypeName { get; set; }
public TypeTemplate TypeTemplate => TypeGuid == null ? null : Warehouse.GetTemplateByClassId((Guid)TypeGuid);
//namespace Esiur.Resource.Template;
//public struct TemplateDataType
//{
// public DataType Type { get; set; }
// //public string TypeName { get; set; }
// public TypeTemplate TypeTemplate => TypeGuid == null ? null : Warehouse.GetTemplateByClassId((Guid)TypeGuid);
public Guid? TypeGuid { get; set; }
//public TemplateDataType(DataType type, string typeName)
//{
// Type = type;
// TypeName = typeName;
//}
// public Guid? TypeGuid { get; set; }
// public bool IsNullable { get; set; }
// //public TemplateDataType(DataType type, string typeName)
// //{
// // Type = type;
// // TypeName = typeName;
// //}
public static TemplateDataType FromType(Type type)
{
var t = type switch
{
{ IsArray: true } => type.GetElementType(),
{ IsEnum: true } => type.GetEnumUnderlyingType(),
(_) => type
};
DataType dt = t switch
{
_ when t == typeof(bool) => DataType.Bool,
_ when t == typeof(char) => DataType.Char,
_ when t == typeof(byte) => DataType.UInt8,
_ when t == typeof(sbyte) => DataType.Int8,
_ when t == typeof(short) => DataType.Int16,
_ when t == typeof(ushort) => DataType.UInt16,
_ when t == typeof(int) => DataType.Int32,
_ when t == typeof(uint) => DataType.UInt32,
_ when t == typeof(long) => DataType.Int64,
_ when t == typeof(ulong) => DataType.UInt64,
_ when t == typeof(float) => DataType.Float32,
_ when t == typeof(double) => DataType.Float64,
_ when t == typeof(decimal) => DataType.Decimal,
_ when t == typeof(string) => DataType.String,
_ when t == typeof(DateTime) => DataType.DateTime,
_ when t == typeof(IResource) => DataType.Void, // Dynamic resource (unspecified type)
_ when t == typeof(IRecord) => DataType.Void, // Dynamic record (unspecified type)
_ when typeof(Structure).IsAssignableFrom(t) || t == typeof(ExpandoObject) => DataType.Structure,
_ when Codec.ImplementsInterface(t, typeof(IResource)) => DataType.Resource,
_ when Codec.ImplementsInterface(t, typeof(IRecord)) => DataType.Record,
_ => DataType.Void
};
// public static TemplateDataType FromType(Type type)
// {
Guid? typeGuid = null;
// bool isList = typeof(ICollection).IsAssignableFrom(type);
if (dt == DataType.Resource || dt == DataType.Record)
typeGuid = TypeTemplate.GetTypeGuid(t);
// var t = type switch
// {
if (type.IsArray)
dt = (DataType)((byte)dt | 0x80);
// { IsArray: true } => type.GetElementType(),
// { IsEnum: true } => type.GetEnumUnderlyingType(),
// _ when isList => Codec.GetGenericListType(type),
// (_) => type
// };
return new TemplateDataType()
{
Type = dt,
TypeGuid = typeGuid
};
}
public byte[] Compose()
{
if (Type == DataType.Resource ||
Type == DataType.ResourceArray ||
Type == DataType.Record ||
Type == DataType.RecordArray)
{
var guid = DC.ToBytes((Guid)TypeGuid);
return new BinaryList()
.AddUInt8((byte)Type)
.AddUInt8Array(guid).ToArray();
}
else
return new byte[] { (byte)Type };
}
public override string ToString() => Type.ToString() + TypeTemplate != null ? "<" + TypeTemplate.ClassName + ">" : "";
// DataType dt = t switch
// {
// _ when t == typeof(bool) => DataType.Bool,
// _ when t == typeof(char) => DataType.Char,
// _ when t == typeof(byte) => DataType.UInt8,
// _ when t == typeof(sbyte) => DataType.Int8,
// _ when t == typeof(short) => DataType.Int16,
// _ when t == typeof(ushort) => DataType.UInt16,
// _ when t == typeof(int) => DataType.Int32,
// _ when t == typeof(uint) => DataType.UInt32,
// _ when t == typeof(long) => DataType.Int64,
// _ when t == typeof(ulong) => DataType.UInt64,
// _ when t == typeof(float) => DataType.Float32,
// _ when t == typeof(double) => DataType.Float64,
// _ when t == typeof(decimal) => DataType.Decimal,
// _ when t == typeof(string) => DataType.String,
// _ when t == typeof(DateTime) => DataType.DateTime,
// _ when t == typeof(IResource) => DataType.Void, // Dynamic resource (unspecified type)
// _ when t == typeof(IRecord) => DataType.Void, // Dynamic record (unspecified type)
// _ when typeof(Structure).IsAssignableFrom(t) || t == typeof(ExpandoObject) => DataType.Structure,
// _ when Codec.ImplementsInterface(t, typeof(IResource)) => DataType.Resource,
// _ when Codec.ImplementsInterface(t, typeof(IRecord)) => DataType.Record,
// _ => DataType.Void
// };
public static (uint, TemplateDataType) Parse(byte[] data, uint offset)
{
var type = (DataType)data[offset++];
if (type == DataType.Resource ||
type == DataType.ResourceArray ||
type == DataType.Record ||
type == DataType.RecordArray)
{
var guid = data.GetGuid(offset);
return (17, new TemplateDataType() { Type = type, TypeGuid = guid });
}
else
return (1, new TemplateDataType() { Type = type });
}
}
// Guid? typeGuid = null;
// if (dt == DataType.Resource || dt == DataType.Record)
// typeGuid = TypeTemplate.GetTypeGuid(t);
// if (type.IsArray || isList)
// dt = (DataType)((byte)dt | 0x80);
// return new TemplateDataType()
// {
// Type = dt,
// TypeGuid = typeGuid,
// IsNullable = Nullable.GetUnderlyingType(type) != null
// };
// }
// public byte[] Compose()
// {
// if (Type == DataType.Resource ||
// Type == DataType.ResourceArray ||
// Type == DataType.Record ||
// Type == DataType.RecordArray)
// {
// var guid = DC.ToBytes((Guid)TypeGuid);
// if (IsNullable)
// {
// return new BinaryList()
// .AddUInt8((byte)((byte)Type | 0x40))
// .AddUInt8Array(guid).ToArray();
// } else
// {
// return new BinaryList()
// .AddUInt8((byte)Type)
// .AddUInt8Array(guid).ToArray();
// }
// }
// else if (IsNullable)
// return new byte[] { (byte)((byte)Type | 0x40) };
// else
// return new byte[] { (byte)Type };
// }
// public override string ToString() => Type.ToString() + (IsNullable ? "?":"" )
// + TypeTemplate != null ? "<" + TypeTemplate.ClassName + ">" : "";
// public static (uint, TemplateDataType) Parse(byte[] data, uint offset)
// {
// bool isNullable = (data[offset] & 0x40) > 0;
// var type = (DataType)(data[offset++] & 0xBF);
// if (type == DataType.Resource ||
// type == DataType.ResourceArray ||
// type == DataType.Record ||
// type == DataType.RecordArray)
// {
// var guid = data.GetGuid(offset);
// return (17, new TemplateDataType() { Type = type, TypeGuid = guid , IsNullable = isNullable});
// }
// else
// return (1, new TemplateDataType() { Type = type, IsNullable = isNullable });
// }
//}

View File

@ -9,4 +9,5 @@ public enum TemplateType : byte
Resource,
Record,
Wrapper,
Enum
}

View File

@ -22,20 +22,26 @@ public class TypeTemplate
{
protected Guid classId;
protected string className;
protected List<MemberTemplate> members = new List<MemberTemplate>();
protected List<FunctionTemplate> functions = new List<FunctionTemplate>();
protected List<EventTemplate> events = new List<EventTemplate>();
protected List<PropertyTemplate> properties = new List<PropertyTemplate>();
protected List<AttributeTemplate> attributes = new List<AttributeTemplate>();
protected int version;
protected TemplateType templateType;
protected Guid? parentId;
string className;
List<MemberTemplate> members = new List<MemberTemplate>();
List<FunctionTemplate> functions = new List<FunctionTemplate>();
List<EventTemplate> events = new List<EventTemplate>();
List<PropertyTemplate> properties = new List<PropertyTemplate>();
List<AttributeTemplate> attributes = new List<AttributeTemplate>();
List<ConstantTemplate> constants = new();
int version;
TemplateType templateType;
// protected TemplateType
//bool isReady;
protected byte[] content;
public Guid? ParentId => parentId;
public byte[] Content
{
get { return content; }
@ -45,9 +51,7 @@ public class TypeTemplate
public Type DefinedType { get; set; }
public Type ParentDefinedType { get; set; }
//public MemberTemplate GetMemberTemplate(MemberInfo member)
//{
@ -145,7 +149,7 @@ public class TypeTemplate
get { return properties.ToArray(); }
}
public ConstantTemplate[] Constants => constants.ToArray();
public TypeTemplate()
{
@ -166,7 +170,7 @@ public class TypeTemplate
static Type GetElementType(Type type) => type switch
{
{ IsArray: true } => type.GetElementType(),
{ IsEnum: true } => type.GetEnumUnderlyingType(),
// { IsEnum: true } => type.GetEnumUnderlyingType(),
(_) => type
};
@ -177,8 +181,20 @@ public class TypeTemplate
var list = new List<TypeTemplate>();
// Add self
list.Add(template);
// Add parents
var parentType = template.ParentDefinedType;
// Get parents
while (parentType != null)
{
var parentTemplate = Warehouse.GetTemplateByType(parentType);
list.Add(parentTemplate);
parentType = parentTemplate.ParentDefinedType;
}
Action<TypeTemplate, List<TypeTemplate>> getDependenciesFunc = null;
getDependenciesFunc = (TypeTemplate tmp, List<TypeTemplate> bag) =>
@ -186,8 +202,8 @@ public class TypeTemplate
if (template.DefinedType == null)
return;
// functions
foreach (var f in tmp.functions)
// functions
foreach (var f in tmp.functions)
{
var frtt = Warehouse.GetTemplateByType(GetElementType(f.MethodInfo.ReturnType));
if (frtt != null)
@ -214,8 +230,8 @@ public class TypeTemplate
}
}
// skip DistributedConnection argument
if (args.Length > 0)
// skip DistributedConnection argument
if (args.Length > 0)
{
var last = args.Last();
if (last.ParameterType != typeof(DistributedConnection))
@ -234,8 +250,8 @@ public class TypeTemplate
}
// properties
foreach (var p in tmp.properties)
// properties
foreach (var p in tmp.properties)
{
var pt = Warehouse.GetTemplateByType(GetElementType(p.PropertyInfo.PropertyType));
if (pt != null)
@ -248,8 +264,8 @@ public class TypeTemplate
}
}
// events
foreach (var e in tmp.events)
// events
foreach (var e in tmp.events)
{
var et = Warehouse.GetTemplateByType(GetElementType(e.EventInfo.EventHandlerType.GenericTypeArguments[0]));
@ -268,6 +284,15 @@ public class TypeTemplate
return list.ToArray();
}
public string GetTypeAnnotationName(Type type)
{
var nullType = Nullable.GetUnderlyingType(type);
if (nullType == null)
return type.Name;
else
return type.Name + "?";
}
public TypeTemplate(Type type, bool addToWarehouse = false)
{
if (Codec.InheritsClass(type, typeof(DistributedResource)))
@ -276,6 +301,8 @@ public class TypeTemplate
templateType = TemplateType.Resource;
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
templateType = TemplateType.Record;
else if (type.IsEnum)
templateType = TemplateType.Enum;
else
throw new Exception("Type must implement IResource, IRecord or inherit from DistributedResource.");
@ -291,32 +318,56 @@ public class TypeTemplate
className = type.FullName;
//Console.WriteLine($"Creating {className}");
// set guid
classId = GetTypeGuid(className);
if (addToWarehouse)
Warehouse.PutTemplate(this);
#if NETSTANDARD
PropertyInfo[] propsInfo = type.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
EventInfo[] eventsInfo = type.GetTypeInfo().GetEvents(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
MethodInfo[] methodsInfo = type.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Instance); // | BindingFlags.DeclaredOnly);
#else
PropertyInfo[] propsInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
EventInfo[] eventsInfo = type.GetEvents(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
MethodInfo[] methodsInfo = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
#endif
PropertyInfo[] propsInfo = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
EventInfo[] eventsInfo = type.GetEvents(BindingFlags.Public | BindingFlags.Instance);// | BindingFlags.DeclaredOnly);
MethodInfo[] methodsInfo = type.GetMethods(BindingFlags.Public | BindingFlags.Instance); // | BindingFlags.DeclaredOnly);
FieldInfo[] constantsInfo = type.GetFields(BindingFlags.Public | BindingFlags.Static);
bool classIsPublic = type.IsEnum || (type.GetCustomAttribute<PublicAttribute>() != null);
bool classIsPublic = type.GetCustomAttribute<PublicAttribute>() != null;
byte i = 0;
if (classIsPublic)
{
foreach (var ci in constantsInfo)
{
var privateAttr = ci.GetCustomAttribute<PrivateAttribute>(true);
var annotationAttr = ci.GetCustomAttribute<AnnotationAttribute>(true);
if (privateAttr != null)
continue;
var valueType = RepresentationType.FromType(ci.FieldType);
if (valueType == null)
throw new Exception($"Unsupported type `{ci.FieldType}` in constant `{type.Name}.{ci.Name}`");
var value = ci.GetValue(null);
if (templateType == TemplateType.Enum)
value = Convert.ChangeType(value, ci.FieldType.GetEnumUnderlyingType());
var ct = new ConstantTemplate(this, i++, ci.Name, ci.DeclaringType != type, valueType, value, annotationAttr?.Annotation);
constants.Add(ct);
}
i = 0;
foreach (var pi in propsInfo)
{
var privateAttr = pi.GetCustomAttribute<PrivateAttribute>(true);
@ -326,7 +377,12 @@ public class TypeTemplate
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
var pt = new PropertyTemplate(this, i++, pi.Name, TemplateDataType.FromType(pi.PropertyType));
var attrType = RepresentationType.FromType(pi.PropertyType);
if (attrType == null)
throw new Exception($"Unsupported type `{pi.PropertyType}` in property `{type.Name}.{pi.Name}`");
var pt = new PropertyTemplate(this, i++, pi.Name, pi.DeclaringType != type, attrType);
if (storageAttr != null)
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
@ -334,7 +390,7 @@ public class TypeTemplate
if (annotationAttr != null)
pt.ReadExpansion = annotationAttr.Annotation;
else
pt.ReadExpansion = pi.PropertyType.Name;
pt.ReadExpansion = GetTypeAnnotationName(pi.PropertyType);
pt.PropertyInfo = pi;
//pt.Serilize = publicAttr.Serialize;
@ -346,7 +402,7 @@ public class TypeTemplate
if (attributeAttr != null)
{
var an = attributeAttr.Name ?? pi.Name;
var at = new AttributeTemplate(this, 0, an);
var at = new AttributeTemplate(this, 0, an, pi.DeclaringType != type);
at.PropertyInfo = pi;
attributes.Add(at);
}
@ -356,69 +412,109 @@ public class TypeTemplate
if (templateType == TemplateType.Resource)
{
i = 0;
foreach (var ei in eventsInfo)
{
var privateAttr = ei.GetCustomAttribute<PrivateAttribute>(true);
if (privateAttr == null)
{
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
var listenableAttr = ei.GetCustomAttribute<ListenableAttribute>(true);
if (privateAttr != null)
continue;
var argType = ei.EventHandlerType.GenericTypeArguments[0];
var et = new EventTemplate(this, i++, ei.Name, TemplateDataType.FromType(argType));
et.EventInfo = ei;
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
var listenableAttr = ei.GetCustomAttribute<ListenableAttribute>(true);
if (annotationAttr != null)
et.Expansion = annotationAttr.Annotation;
var argType = ei.EventHandlerType.GenericTypeArguments[0];
var evtType = RepresentationType.FromType(argType);
if (listenableAttr != null)
et.Listenable = true;
if (evtType == null)
throw new Exception($"Unsupported type `{argType}` in event `{type.Name}.{ei.Name}`");
events.Add(et);
}
var et = new EventTemplate(this, i++, ei.Name, ei.DeclaringType != type, evtType);
et.EventInfo = ei;
if (annotationAttr != null)
et.Expansion = annotationAttr.Annotation;
if (listenableAttr != null)
et.Listenable = true;
events.Add(et);
}
i = 0;
foreach (MethodInfo mi in methodsInfo)
{
var privateAttr = mi.GetCustomAttribute<PrivateAttribute>(true);
if (privateAttr == null)
if (privateAttr != null)
continue;
var annotationAttr = mi.GetCustomAttribute<AnnotationAttribute>(true);
var returnType = RepresentationType.FromType(mi.ReturnType);
if (returnType == null)
throw new Exception($"Unsupported type {mi.ReturnType} in method {type.Name}.{mi.Name} return");
var args = mi.GetParameters();
if (args.Length > 0)
{
var annotationAttr = mi.GetCustomAttribute<AnnotationAttribute>(true);
if (args.Last().ParameterType == typeof(DistributedConnection))
args = args.Take(args.Count() - 1).ToArray();
}
var returnType = TemplateDataType.FromType(mi.ReturnType);
var arguments = args.Select(x =>
{
var argType = RepresentationType.FromType(x.ParameterType);
if (argType == null)
throw new Exception($"Unsupported type `{x.ParameterType}` in method `{type.Name}.{mi.Name}` parameter `{x.Name}`");
var args = mi.GetParameters();
if (args.Length > 0)
{
if (args.Last().ParameterType == typeof(DistributedConnection))
args = args.Take(args.Count() - 1).ToArray();
}
var arguments = args.Select(x => new ArgumentTemplate()
return new ArgumentTemplate()
{
Name = x.Name,
Type = TemplateDataType.FromType(x.ParameterType),
ParameterInfo = x
}).ToArray();
Type = argType,
ParameterInfo = x,
Optional = x.IsOptional
};
}).ToArray();
var ft = new FunctionTemplate(this, i++, mi.Name, arguments, returnType);// mi.ReturnType == typeof(void));
var ft = new FunctionTemplate(this, i++, mi.Name, mi.DeclaringType != type, arguments, returnType);// mi.ReturnType == typeof(void));
if (annotationAttr != null)
ft.Expansion = annotationAttr.Annotation;
else
ft.Expansion = "(" + String.Join(",", mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection)).Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name;
if (annotationAttr != null)
ft.Expansion = annotationAttr.Annotation;
else
ft.Expansion = "(" + String.Join(",", mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection)).Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name;
ft.MethodInfo = mi;
functions.Add(ft);
}
ft.MethodInfo = mi;
functions.Add(ft);
}
}
}
else
{
foreach (var ci in constantsInfo)
{
var publicAttr = ci.GetCustomAttribute<PublicAttribute>(true);
var annotationAttr = ci.GetCustomAttribute<AnnotationAttribute>(true);
if (publicAttr == null)
continue;
var valueType = RepresentationType.FromType(ci.FieldType);
if (valueType == null)
throw new Exception($"Unsupported type `{ci.FieldType}` in constant `{type.Name}.{ci.Name}`");
var value = ci.GetValue(null);
var ct = new ConstantTemplate(this, i++, ci.Name, ci.DeclaringType != type, valueType, value, annotationAttr?.Annotation);
constants.Add(ct);
}
i = 0;
foreach (var pi in propsInfo)
{
@ -428,17 +524,22 @@ public class TypeTemplate
{
var annotationAttr = pi.GetCustomAttribute<AnnotationAttribute>(true);
var storageAttr = pi.GetCustomAttribute<StorageAttribute>(true);
var valueType = TemplateDataType.FromType(pi.PropertyType);
var valueType = RepresentationType.FromType(pi.PropertyType);
if (valueType == null)
throw new Exception($"Unsupported type `{pi.PropertyType}` in property `{type.Name}.{pi.Name}`");
var pn = publicAttr.Name ?? pi.Name;
var pt = new PropertyTemplate(this, i++, pn, valueType);//, rp.ReadExpansion, rp.WriteExpansion, rp.Storage);
var pt = new PropertyTemplate(this, i++, pn, pi.DeclaringType != type, valueType);//, rp.ReadExpansion, rp.WriteExpansion, rp.Storage);
if (storageAttr != null)
pt.Recordable = storageAttr.Mode == StorageMode.Recordable;
if (annotationAttr != null)
pt.ReadExpansion = annotationAttr.Annotation;
else
pt.ReadExpansion = pi.PropertyType.Name;
pt.ReadExpansion = GetTypeAnnotationName(pi.PropertyType);
pt.PropertyInfo = pi;
//pt.Serilize = publicAttr.Serialize;
@ -450,7 +551,7 @@ public class TypeTemplate
if (attributeAttr != null)
{
var pn = attributeAttr.Name ?? pi.Name;
var at = new AttributeTemplate(this, 0, pn);
var at = new AttributeTemplate(this, 0, pn, pi.DeclaringType != type);
at.PropertyInfo = pi;
attributes.Add(at);
}
@ -464,65 +565,85 @@ public class TypeTemplate
foreach (var ei in eventsInfo)
{
var publicAttr = ei.GetCustomAttribute<PublicAttribute>(true);
if (publicAttr != null)
{
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
var listenableAttr = ei.GetCustomAttribute<ListenableAttribute>(true);
var argType = ei.EventHandlerType.GenericTypeArguments[0];
if (publicAttr == null)
continue;
var en = publicAttr.Name ?? ei.Name;
var et = new EventTemplate(this, i++, en, TemplateDataType.FromType(argType));
et.EventInfo = ei;
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true);
var listenableAttr = ei.GetCustomAttribute<ListenableAttribute>(true);
if (annotationAttr != null)
et.Expansion = annotationAttr.Annotation;
var argType = ei.EventHandlerType.GenericTypeArguments[0];
if (listenableAttr != null)
et.Listenable = true;
var en = publicAttr.Name ?? ei.Name;
events.Add(et);
}
var evtType = RepresentationType.FromType(argType);
if (evtType == null)
throw new Exception($"Unsupported type `{argType}` in event `{type.Name}.{ei.Name}`");
var et = new EventTemplate(this, i++, en, ei.DeclaringType != type, evtType);
et.EventInfo = ei;
if (annotationAttr != null)
et.Expansion = annotationAttr.Annotation;
if (listenableAttr != null)
et.Listenable = true;
events.Add(et);
}
i = 0;
foreach (MethodInfo mi in methodsInfo)
{
var publicAttr = mi.GetCustomAttribute<PublicAttribute>(true);
if (publicAttr != null)
if (publicAttr == null)
continue;
var annotationAttr = mi.GetCustomAttribute<AnnotationAttribute>(true);
var returnType = RepresentationType.FromType(mi.ReturnType);
if (returnType == null)
throw new Exception($"Unsupported type `{mi.ReturnType}` in method `{type.Name}.{mi.Name}` return");
var args = mi.GetParameters();
if (args.Length > 0)
{
var annotationAttr = mi.GetCustomAttribute<AnnotationAttribute>(true);
var returnType = TemplateDataType.FromType(mi.ReturnType);
if (args.Last().ParameterType == typeof(DistributedConnection))
args = args.Take(args.Count() - 1).ToArray();
}
var args = mi.GetParameters();
var arguments = args.Select(x =>
{
var argType = RepresentationType.FromType(x.ParameterType);
if (argType == null)
throw new Exception($"Unsupported type `{x.ParameterType}` in method `{type.Name}.{mi.Name}` parameter `{x.Name}`");
if (args.Length > 0)
{
if (args.Last().ParameterType == typeof(DistributedConnection))
args = args.Take(args.Count() - 1).ToArray();
}
var arguments = args.Select(x => new ArgumentTemplate()
return new ArgumentTemplate()
{
Name = x.Name,
Type = TemplateDataType.FromType(x.ParameterType),
ParameterInfo = x
})
.ToArray();
Type = argType,
ParameterInfo = x,
Optional = x.IsOptional
};
})
.ToArray();
var fn = publicAttr.Name ?? mi.Name;
var fn = publicAttr.Name ?? mi.Name;
var ft = new FunctionTemplate(this, i++, fn, arguments, returnType);// mi.ReturnType == typeof(void));
var ft = new FunctionTemplate(this, i++, fn, mi.DeclaringType != type, arguments, returnType);// mi.ReturnType == typeof(void));
if (annotationAttr != null)
ft.Expansion = annotationAttr.Annotation;
else
ft.Expansion = "(" + String.Join(",", mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection)).Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name;
if (annotationAttr != null)
ft.Expansion = annotationAttr.Annotation;
else
ft.Expansion = "(" + String.Join(",", mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection)).Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name;
ft.MethodInfo = mi;
functions.Add(ft);
ft.MethodInfo = mi;
functions.Add(ft);
}
}
}
}
@ -537,15 +658,41 @@ public class TypeTemplate
for (i = 0; i < properties.Count; i++)
members.Add(properties[i]);
// append constants
for (i = 0; i < constants.Count; i++)
members.Add(constants[i]);
// bake it binarily
var b = new BinaryList();
b.AddUInt8((byte)templateType)
.AddGuid(classId)
.AddUInt8((byte)className.Length)
.AddString(className)
.AddInt32(version)
.AddUInt16((ushort)members.Count);
// find the first parent type that implements IResource
if (HasParent(type))
{
// find the first parent type that implements IResource
var ParentDefinedType = ResourceProxy.GetBaseType(type.BaseType);
var parentId = GetTypeGuid(ParentDefinedType.FullName);
b.AddUInt8((byte)(0x80 | (byte)templateType))
.AddGuid(classId)
.AddUInt8((byte)className.Length)
.AddString(className)
.AddGuid(parentId)
.AddInt32(version)
.AddUInt16((ushort)members.Count);
}
else
{
b.AddUInt8((byte)templateType)
.AddGuid(classId)
.AddUInt8((byte)className.Length)
.AddString(className)
.AddInt32(version)
.AddUInt16((ushort)members.Count);
}
foreach (var ft in functions)
b.AddUInt8Array(ft.Compose());
@ -553,11 +700,32 @@ public class TypeTemplate
b.AddUInt8Array(pt.Compose());
foreach (var et in events)
b.AddUInt8Array(et.Compose());
foreach (var ct in constants)
b.AddUInt8Array(ct.Compose());
content = b.ToArray();
}
public static bool HasParent (Type type)
{
var parent = type.BaseType;
if (parent == typeof(Resource)
|| parent == typeof(Record))
return false;
while (parent != null)
{
if (parent.GetInterfaces().Contains(typeof(IResource))
|| parent.GetInterfaces().Contains(typeof(IRecord)))
return true;
parent = parent.BaseType;
}
return false;
}
public static TypeTemplate Parse(byte[] data)
{
return Parse(data, 0, (uint)data.Length);
@ -576,17 +744,27 @@ public class TypeTemplate
var od = new TypeTemplate();
od.content = data.Clip(offset, contentLength);
od.templateType = (TemplateType)data[offset++];
var hasParent = (data[offset] & 0x80) > 0;
od.templateType = (TemplateType)(data[offset++] & 0xF);
od.classId = data.GetGuid(offset);
offset += 16;
od.className = data.GetString(offset + 1, data[offset]);
offset += (uint)data[offset] + 1;
od.version = data.GetInt32(offset);
if (od.className == "Test.MyChildRecord")
Console.WriteLine();
if (hasParent)
{
od.parentId = data.GetGuid(offset);
offset += 16;
}
od.version = data.GetInt32(offset, Endian.Little);
offset += 4;
ushort methodsCount = data.GetUInt16(offset);
ushort methodsCount = data.GetUInt16(offset, Endian.Little);
offset += 2;
byte functionIndex = 0;
@ -595,7 +773,8 @@ public class TypeTemplate
for (int i = 0; i < methodsCount; i++)
{
var type = data[offset] >> 5;
var inherited = (data[offset] & 0x80) > 0;
var type = (data[offset] >> 5) & 0x3;
if (type == 0) // function
{
@ -606,7 +785,7 @@ public class TypeTemplate
offset += (uint)data[offset] + 1;
// return type
var (rts, returnType) = TemplateDataType.Parse(data, offset);
var (rts, returnType) = RepresentationType.Parse(data, offset);
offset += rts;
// arguments count
@ -615,7 +794,7 @@ public class TypeTemplate
for (var a = 0; a < argsCount; a++)
{
var (cs, argType) = ArgumentTemplate.Parse(data, offset);
var (cs, argType) = ArgumentTemplate.Parse(data, offset, a);
arguments.Add(argType);
offset += cs;
}
@ -623,13 +802,13 @@ public class TypeTemplate
// arguments
if (hasExpansion) // expansion ?
{
var cs = data.GetUInt32(offset);
var cs = data.GetUInt32(offset, Endian.Little);
offset += 4;
expansion = data.GetString(offset, cs);
offset += cs;
}
var ft = new FunctionTemplate(od, functionIndex++, name, arguments.ToArray(), returnType, expansion);
var ft = new FunctionTemplate(od, functionIndex++, name, inherited, arguments.ToArray(), returnType, expansion);
od.functions.Add(ft);
}
@ -646,13 +825,13 @@ public class TypeTemplate
offset += (uint)data[offset] + 1;
var (dts, valueType) = TemplateDataType.Parse(data, offset);
var (dts, valueType) = RepresentationType.Parse(data, offset);
offset += dts;
if (hasReadExpansion) // expansion ?
{
var cs = data.GetUInt32(offset);
var cs = data.GetUInt32(offset, Endian.Little);
offset += 4;
readExpansion = data.GetString(offset, cs);
offset += cs;
@ -660,13 +839,13 @@ public class TypeTemplate
if (hasWriteExpansion) // expansion ?
{
var cs = data.GetUInt32(offset);
var cs = data.GetUInt32(offset, Endian.Little);
offset += 4;
writeExpansion = data.GetString(offset, cs);
offset += cs;
}
var pt = new PropertyTemplate(od, propertyIndex++, name, valueType, readExpansion, writeExpansion, recordable);
var pt = new PropertyTemplate(od, propertyIndex++, name, inherited, valueType, readExpansion, writeExpansion, recordable);
od.properties.Add(pt);
}
@ -680,23 +859,52 @@ public class TypeTemplate
var name = data.GetString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, (int)data[offset]);
offset += (uint)data[offset] + 1;
var (dts, argType) = TemplateDataType.Parse(data, offset);
var (dts, argType) = RepresentationType.Parse(data, offset);
offset += dts;
if (hasExpansion) // expansion ?
{
var cs = data.GetUInt32(offset);
var cs = data.GetUInt32(offset, Endian.Little);
offset += 4;
expansion = data.GetString(offset, cs);
offset += cs;
}
var et = new EventTemplate(od, eventIndex++, name, argType, expansion, listenable);
var et = new EventTemplate(od, eventIndex++, name, inherited, argType, expansion, listenable);
od.events.Add(et);
}
// constant
else if (type == 3)
{
string expansion = null;
var hasExpansion = ((data[offset++] & 0x10) == 0x10);
var name = data.GetString(offset + 1, data[offset]);
offset += (uint)data[offset] + 1;
var (dts, valueType) = RepresentationType.Parse(data, offset);
offset += dts;
(dts, var value) = Codec.Parse(data, offset, null);
offset += dts;
if (hasExpansion) // expansion ?
{
var cs = data.GetUInt32(offset, Endian.Little);
offset += 4;
expansion = data.GetString(offset, cs);
offset += cs;
}
var ct = new ConstantTemplate(od, eventIndex++, name, inherited, valueType, value.Result, expansion);
od.constants.Add(ct);
}
}
// append signals
@ -708,22 +916,9 @@ public class TypeTemplate
// append properties
for (int i = 0; i < od.properties.Count; i++)
od.members.Add(od.properties[i]);
//od.isReady = true;
/*
var oo = owner.Socket.Engine.GetObjectDescription(od.GUID);
if (oo != null)
{
Console.WriteLine("Already there ! description");
return oo;
}
else
{
owner.Socket.Engine.AddObjectDescription(od);
return od;
}
*/
// append constants
for (int i = 0; i < od.constants.Count; i++)
od.members.Add(od.constants[i]);
return od;
}

View File

@ -53,8 +53,6 @@ public static class Warehouse
static uint resourceCounter = 0;
//static KeyList<Guid, TypeTemplate> templates = new KeyList<Guid, TypeTemplate>();
//static KeyList<Guid, TypeTemplate> wrapperTemplates = new KeyList<Guid, TypeTemplate>();
static KeyList<TemplateType, KeyList<Guid, TypeTemplate>> templates
= new KeyList<TemplateType, KeyList<Guid, TypeTemplate>>()
@ -63,6 +61,7 @@ public static class Warehouse
[TemplateType.Resource] = new KeyList<Guid, TypeTemplate>(),
[TemplateType.Record] = new KeyList<Guid, TypeTemplate>(),
[TemplateType.Wrapper] = new KeyList<Guid, TypeTemplate>(),
[TemplateType.Enum] = new KeyList<Guid, TypeTemplate>(),
};
static bool warehouseIsOpen = false;
@ -141,6 +140,12 @@ public static class Warehouse
{
PutTemplate(new TypeTemplate(t));
}
var enumsTypes = (Type[])generatedType.GetProperty("Enums").GetValue(null);
foreach (var t in recordTypes)
{
PutTemplate(new TypeTemplate(t));
}
}
}
}
@ -590,7 +595,7 @@ public static class Warehouse
resource.Instance = new Instance(resourceCounter++, instanceName, resource, store, customTemplate, age);
if (attributes != null)
resource.Instance.SetAttributes(Structure.FromObject(attributes));
resource.Instance.SetAttributes(Map<string,object>.FromObject(attributes));
if (manager != null)
resource.Instance.Managers.Add(manager);
@ -686,7 +691,7 @@ public static class Warehouse
if (properties != null)
{
var ps = Structure.FromObject(properties);
var ps = Map<string,object>.FromObject(properties);
foreach (var p in ps)
{
@ -768,6 +773,8 @@ public static class Warehouse
templateType = TemplateType.Resource;
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
templateType = TemplateType.Record;
else if (type.IsEnum)
templateType = TemplateType.Enum;
else
return null;
@ -781,7 +788,10 @@ public static class Warehouse
// loaded ?
if (template == null)
{
template = new TypeTemplate(baseType, true);
TypeTemplate.GetDependencies(template);
}
return template;
}
@ -805,6 +815,12 @@ public static class Warehouse
if (template != null)
return template;
// look in enums
template = templates[TemplateType.Enum][classId];
if (template != null)
return template;
// look in wrappers
template = templates[TemplateType.Wrapper][classId];
return template;

View File

@ -53,11 +53,11 @@ public class CACertificate : Certificate
uint oOffset = offset;
this.id = DC.GetUInt64(data, offset);
this.id = DC.GetUInt64(data, offset, Endian.Little);
offset += 8;
this.issueDate = DC.GetDateTime(data, offset);
this.issueDate = DC.GetDateTime(data, offset, Endian.Little);
offset += 8;
this.expireDate = DC.GetDateTime(data, offset);
this.expireDate = DC.GetDateTime(data, offset, Endian.Little);
offset += 8;
this.hashFunction = (HashFunctionType)(data[offset++] >> 4);
@ -77,7 +77,7 @@ public class CACertificate : Certificate
offset += exponentLength;
uint keySize = DC.GetUInt16(data, offset);
uint keySize = DC.GetUInt16(data, offset, Endian.Little);
offset += 2;
key.Modulus = DC.Clip(data, offset, keySize);

View File

@ -79,19 +79,19 @@ public class DomainCertificate : Certificate
{
var oOffset = offset;
this.id = DC.GetUInt64(data, offset);
this.id = DC.GetUInt64(data, offset, Endian.Little);
offset += 8;
// load IPs
this.ip = DC.GetUInt32(data, offset);
this.ip = DC.GetUInt32(data, offset, Endian.Little);
offset += 4;
this.ip6 = DC.Clip(data, offset, 16);
offset += 16;
this.issueDate = DC.GetDateTime(data, offset);
this.issueDate = DC.GetDateTime(data, offset, Endian.Little);
offset += 8;
this.expireDate = DC.GetDateTime(data, offset);
this.expireDate = DC.GetDateTime(data, offset, Endian.Little);
offset += 8;
this.domain = Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]);
@ -100,7 +100,7 @@ public class DomainCertificate : Certificate
this.authorityName = (Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]));
offset += (uint)data[offset] + 1;
caId = DC.GetUInt64(data, offset);
caId = DC.GetUInt64(data, offset, Endian.Little);
offset += 8;
var aea = (AsymetricEncryptionAlgorithmType)(data[offset] >> 5);
@ -113,7 +113,7 @@ public class DomainCertificate : Certificate
key.Exponent = DC.Clip(data, offset, exponentLength);
offset += exponentLength;
uint keySize = DC.GetUInt16(data, offset);
uint keySize = DC.GetUInt16(data, offset, Endian.Little);
offset += 2;
key.Modulus = DC.Clip(data, offset, keySize);

View File

@ -79,21 +79,21 @@ public class UserCertificate : Certificate
{
var oOffset = offset;
this.id = DC.GetUInt64(data, offset);
this.id = DC.GetUInt64(data, offset, Endian.Little);
offset += 8;
// load IPs
this.ip = DC.GetUInt32(data, offset);
this.ip = DC.GetUInt32(data, offset, Endian.Little);
offset += 4;
ip6 = DC.Clip(data, offset, 16);
offset += 16;
this.issueDate = DC.GetDateTime(data, offset);
this.issueDate = DC.GetDateTime(data, offset, Endian.Little);
offset += 8;
this.expireDate = DC.GetDateTime(data, offset);
this.expireDate = DC.GetDateTime(data, offset, Endian.Little);
offset += 8;
this.domainId = DC.GetUInt64(data, offset);
this.domainId = DC.GetUInt64(data, offset, Endian.Little);
offset += 8;
this.domain = Encoding.ASCII.GetString(data, (int)offset + 1, data[offset]);
@ -119,7 +119,7 @@ public class UserCertificate : Certificate
offset += exponentLength;
uint keySize = DC.GetUInt16(data, offset);
uint keySize = DC.GetUInt16(data, offset, Endian.Little);
offset += 2;
key.Modulus = DC.Clip(data, offset, keySize);

View File

@ -76,7 +76,7 @@ public static class SHA256
var w = new uint[64];
for (var i = 0; i < 16; i++)
w[i] = data.GetUInt32((uint)(chunk + (i * 4)));
w[i] = data.GetUInt32((uint)(chunk + (i * 4)), Endian.Big);
//for(var i = 16; i < 64; i++)
// w[i] = 0;

View File

@ -49,7 +49,7 @@ public interface IPermissionsManager
/// <returns>Allowed or denined.</returns>
Ruling Applicable(IResource resource, Session session, ActionType action, MemberTemplate member, object inquirer = null);
bool Initialize(Structure settings, IResource resource);
bool Initialize(Map<string, object> settings, IResource resource);
Structure Settings { get; }
Map<string, object> Settings { get; }
}

View File

@ -35,16 +35,16 @@ namespace Esiur.Security.Permissions;
public class StorePermissionsManager : IPermissionsManager
{
Structure settings;
Map<string, object> settings;
public Structure Settings => settings;
public Map<string,object> Settings => settings;
public Ruling Applicable(IResource resource, Session session, ActionType action, MemberTemplate member, object inquirer = null)
{
return resource.Instance.Store.Instance.Applicable(session, action, member, inquirer);
}
public bool Initialize(Structure settings, IResource resource)
public bool Initialize(Map<string,object> settings, IResource resource)
{
this.settings = settings;
return true;

View File

@ -36,18 +36,18 @@ namespace Esiur.Security.Permissions;
public class UserPermissionsManager : IPermissionsManager
{
IResource resource;
Structure settings;
Map<string, object> settings;
public Structure Settings => settings;
public Map<string,object> Settings => settings;
public Ruling Applicable(IResource resource, Session session, ActionType action, MemberTemplate member, object inquirer)
{
Structure userPermissions = null;
Map<string,object> userPermissions = null;
if (settings.ContainsKey(session.RemoteAuthentication.FullName))
userPermissions = settings[session.RemoteAuthentication.FullName] as Structure;
userPermissions = settings[session.RemoteAuthentication.FullName] as Map<string, object>;
else if (settings.ContainsKey("public"))
userPermissions = settings["public"] as Structure;
userPermissions = settings["public"] as Map<string,object>;
else
return Ruling.Denied;
@ -98,7 +98,7 @@ public class UserPermissionsManager : IPermissionsManager
}
else if (userPermissions.ContainsKey(member?.Name))
{
Structure methodPermissions = userPermissions[member.Name] as Structure;
Map<string,object> methodPermissions = userPermissions[member.Name] as Map<string,object>;
if ((string)methodPermissions[action.ToString()] != "yes")
return Ruling.Denied;
}
@ -111,12 +111,12 @@ public class UserPermissionsManager : IPermissionsManager
}
public UserPermissionsManager(Structure settings)
public UserPermissionsManager(Map<string, object> settings)
{
this.settings = settings;
}
public bool Initialize(Structure settings, IResource resource)
public bool Initialize(Map<string, object> settings, IResource resource)
{
this.resource = resource;
this.settings = settings;

View File

@ -16,6 +16,7 @@ public class MemoryStore : IStore
public event DestroyedEvent OnDestroy;
KeyList<uint, IResource> resources = new KeyList<uint, IResource>();
public void Destroy()
@ -69,7 +70,7 @@ public class MemoryStore : IStore
return new AsyncReply<bool>(true);
}
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
public bool Record(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime)
{
throw new NotImplementedException();
}
@ -85,7 +86,7 @@ public class MemoryStore : IStore
return true;
}
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
public bool Modify(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime)
{
return true;
}

View File

@ -64,7 +64,7 @@ public class TemporaryStore : IStore
return new AsyncReply<bool>(true);
}
public bool Record(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
public bool Record(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime)
{
throw new NotImplementedException();
}
@ -80,7 +80,7 @@ public class TemporaryStore : IStore
return true;
}
public bool Modify(IResource resource, string propertyName, object value, ulong age, DateTime dateTime)
public bool Modify(IResource resource, string propertyName, object value, ulong? age, DateTime? dateTime)
{
return true;
}

3
Esiur/TODO Normal file
View File

@ -0,0 +1,3 @@

1- Bin
2- clean

21
Test.Client/Program.cs Normal file
View File

@ -0,0 +1,21 @@

using Esiur.Resource;
namespace Test.Client;
public class App
{
static async Task Main(string[] args)
{
var remote = await Warehouse.Get<MyService>("iip://localhost/mem/service");
var (i, s) = await remote.Tuple2(22, "ZZZZ");
remote.ArrayEvent += (x) => Console.WriteLine(x);
remote.StringEvent += (x)=>Console.WriteLine(x);
await remote.InvokeEvents("Client");
Console.WriteLine(remote);
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Esiur" Version="2.1.1" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31919.166
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test.Client", "Test.Client.csproj", "{EDDCB21B-5929-4218-912A-64B115CBF625}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EDDCB21B-5929-4218-912A-64B115CBF625}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EDDCB21B-5929-4218-912A-64B115CBF625}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDDCB21B-5929-4218-912A-64B115CBF625}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDDCB21B-5929-4218-912A-64B115CBF625}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E70DC657-E2B7-466C-BC0E-9ADC92F62831}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,8 @@
using System;
namespace Esiur {
public static class Generated {
public static Type[] Resources {get;} = new Type[] { typeof(Test.MyService),typeof(Test.MyResource),typeof(Test.MyChildResource),typeof(Test.MyService) };
public static Type[] Records { get; } = new Type[] { typeof(Test.MyRecord) };
public static Type[] Enums { get; } = new Type[] { typeof(Test.SizeEnum) };
}
}

View File

@ -0,0 +1,23 @@
using System;
using Esiur.Resource;
using Esiur.Core;
using Esiur.Data;
using Esiur.Net.IIP;
namespace Test {
public class MyChildResource : Test.MyResource {
public MyChildResource(DistributedConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) {}
public MyChildResource() {}
public AsyncReply<int> ChildMethod(string childName) {
var rt = new AsyncReply<int>();
_InvokeByArrayArguments(0, new object[] { childName })
.Then(x => rt.Trigger((int)x))
.Error(x => rt.TriggerError(x))
.Chunk(x => rt.TriggerChunk(x));
return rt; }
public string ChildName {
get => (string)properties[0];
set => _Set(0, value);
}
}
}

View File

@ -0,0 +1,16 @@
using System;
using Esiur.Resource;
using Esiur.Core;
using Esiur.Data;
using Esiur.Net.IIP;
namespace Test {
[Public] public class MyRecord : IRecord {
public string Name { get; set; }
public int Id { get; set; }
public double Score { get; set; }
}
}

View File

@ -0,0 +1,20 @@
using System;
using Esiur.Resource;
using Esiur.Core;
using Esiur.Data;
using Esiur.Net.IIP;
namespace Test {
public class MyResource : DistributedResource {
public MyResource(DistributedConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) {}
public MyResource() {}
public string Description {
get => (string)properties[0];
set => _Set(0, value);
}
public int CategoryId {
get => (int)properties[1];
set => _Set(1, value);
}
}
}

View File

@ -0,0 +1,257 @@
using System;
using Esiur.Resource;
using Esiur.Core;
using Esiur.Data;
using Esiur.Net.IIP;
namespace Test {
public class MyService : DistributedResource {
public MyService(DistributedConnection connection, uint instanceId, ulong age, string link) : base(connection, instanceId, age, link) {}
public MyService() {}
public AsyncReply<object> Void() {
var rt = new AsyncReply<object>();
_InvokeByArrayArguments(0, new object[] { })
.Then(x => rt.Trigger((object)x))
.Error(x => rt.TriggerError(x))
.Chunk(x => rt.TriggerChunk(x));
return rt; }
public AsyncReply<object> InvokeEvents(string msg) {
var rt = new AsyncReply<object>();
_InvokeByArrayArguments(1, new object[] { msg })
.Then(x => rt.Trigger((object)x))
.Error(x => rt.TriggerError(x))
.Chunk(x => rt.TriggerChunk(x));
return rt; }
public AsyncReply<double> Optional(object a1,int a2,string a3) {
var rt = new AsyncReply<double>();
_InvokeByArrayArguments(2, new object[] { a1, a2, a3 })
.Then(x => rt.Trigger((double)x))
.Error(x => rt.TriggerError(x))
.Chunk(x => rt.TriggerChunk(x));
return rt; }
public AsyncReply<object> Connection(object a1,int a2) {
var rt = new AsyncReply<object>();
_InvokeByArrayArguments(3, new object[] { a1, a2 })
.Then(x => rt.Trigger((object)x))
.Error(x => rt.TriggerError(x))
.Chunk(x => rt.TriggerChunk(x));
return rt; }
public AsyncReply<object> ConnectionOptional(object a1,int a2,string a3) {
var rt = new AsyncReply<object>();
_InvokeByArrayArguments(4, new object[] { a1, a2, a3 })
.Then(x => rt.Trigger((object)x))
.Error(x => rt.TriggerError(x))
.Chunk(x => rt.TriggerChunk(x));
return rt; }
public AsyncReply<(int,string)> Tuple2(int a1,string a2) {
var rt = new AsyncReply<(int,string)>();
_InvokeByArrayArguments(5, new object[] { a1, a2 })
.Then(x => rt.Trigger(((int,string))x))
.Error(x => rt.TriggerError(x))
.Chunk(x => rt.TriggerChunk(x));
return rt; }
public AsyncReply<(int,string,double)> Tuple3(int a1,string a2,double a3) {
var rt = new AsyncReply<(int,string,double)>();
_InvokeByArrayArguments(6, new object[] { a1, a2, a3 })
.Then(x => rt.Trigger(((int,string,double))x))
.Error(x => rt.TriggerError(x))
.Chunk(x => rt.TriggerChunk(x));
return rt; }
public AsyncReply<(int,string,double,bool)> Tuple4(int a1,string a2,double a3,bool a4) {
var rt = new AsyncReply<(int,string,double,bool)>();
_InvokeByArrayArguments(7, new object[] { a1, a2, a3, a4 })
.Then(x => rt.Trigger(((int,string,double,bool))x))
.Error(x => rt.TriggerError(x))
.Chunk(x => rt.TriggerChunk(x));
return rt; }
public int PropertyContext {
get => (int)properties[0];
set => _Set(0, value);
}
public Test.SizeEnum Enum {
get => (Test.SizeEnum)properties[1];
set => _Set(1, value);
}
public Test.MyRecord Record {
get => (Test.MyRecord)properties[2];
set => _Set(2, value);
}
public int[] IntList {
get => (int[])properties[3];
set => _Set(3, value);
}
public IRecord[] RecordsArray {
get => (IRecord[])properties[4];
set => _Set(4, value);
}
public Test.MyRecord[] RecordsList {
get => (Test.MyRecord[])properties[5];
set => _Set(5, value);
}
public Test.MyResource Resource {
get => (Test.MyResource)properties[6];
set => _Set(6, value);
}
public Test.MyChildResource Child {
get => (Test.MyChildResource)properties[7];
set => _Set(7, value);
}
public IResource[] Resources {
get => (IResource[])properties[8];
set => _Set(8, value);
}
public Test.MyService Me {
get => (Test.MyService)properties[9];
set => _Set(9, value);
}
public bool Boolean {
get => (bool)properties[10];
set => _Set(10, value);
}
public bool[] BooleanArray {
get => (bool[])properties[11];
set => _Set(11, value);
}
public byte UInt8 {
get => (byte)properties[12];
set => _Set(12, value);
}
public byte? UInt8Null {
get => (byte?)properties[13];
set => _Set(13, value);
}
public byte[] UInt8Array {
get => (byte[])properties[14];
set => _Set(14, value);
}
public byte?[] UInt8ArrayNull {
get => (byte?[])properties[15];
set => _Set(15, value);
}
public sbyte Int8 {
get => (sbyte)properties[16];
set => _Set(16, value);
}
public sbyte[] Int8Array {
get => (sbyte[])properties[17];
set => _Set(17, value);
}
public char Char16 {
get => (char)properties[18];
set => _Set(18, value);
}
public char[] Char16Array {
get => (char[])properties[19];
set => _Set(19, value);
}
public short Int16 {
get => (short)properties[20];
set => _Set(20, value);
}
public short[] Int16Array {
get => (short[])properties[21];
set => _Set(21, value);
}
public ushort UInt16 {
get => (ushort)properties[22];
set => _Set(22, value);
}
public ushort[] UInt16Array {
get => (ushort[])properties[23];
set => _Set(23, value);
}
public int Int32 {
get => (int)properties[24];
set => _Set(24, value);
}
public int[] Int32Array {
get => (int[])properties[25];
set => _Set(25, value);
}
public uint UInt32 {
get => (uint)properties[26];
set => _Set(26, value);
}
public uint[] UInt32Array {
get => (uint[])properties[27];
set => _Set(27, value);
}
public long Int64 {
get => (long)properties[28];
set => _Set(28, value);
}
public long[] Int64Array {
get => (long[])properties[29];
set => _Set(29, value);
}
public ulong UInt64 {
get => (ulong)properties[30];
set => _Set(30, value);
}
public ulong[] UInt64Array {
get => (ulong[])properties[31];
set => _Set(31, value);
}
public float Float32 {
get => (float)properties[32];
set => _Set(32, value);
}
public float[] Float32Array {
get => (float[])properties[33];
set => _Set(33, value);
}
public double Float64 {
get => (double)properties[34];
set => _Set(34, value);
}
public double[] Float64Array {
get => (double[])properties[35];
set => _Set(35, value);
}
public decimal Float128 {
get => (decimal)properties[36];
set => _Set(36, value);
}
public decimal[] Float128Array {
get => (decimal[])properties[37];
set => _Set(37, value);
}
public string String {
get => (string)properties[38];
set => _Set(38, value);
}
public string[] StringArray {
get => (string[])properties[39];
set => _Set(39, value);
}
public DateTime DateTime {
get => (DateTime)properties[40];
set => _Set(40, value);
}
public Map<string,object> StringMap {
get => (Map<string,object>)properties[41];
set => _Set(41, value);
}
public Map<int,string> IntStringMap {
get => (Map<int,string>)properties[42];
set => _Set(42, value);
}
public object Object {
get => (object)properties[43];
set => _Set(43, value);
}
public object[] ObjectArray {
get => (object[])properties[44];
set => _Set(44, value);
}
public const double PI = 3.14159265358979;
protected override void _EmitEventByIndex(byte index, object args) {
switch (index) {
case 0: StringEvent?.Invoke((string)args); break;
case 1: ArrayEvent?.Invoke((object[])args); break;
}}
public event ResourceEventHandler<string> StringEvent;
public event ResourceEventHandler<object[]> ArrayEvent;
}
}

View File

@ -0,0 +1,15 @@
using System;
using Esiur.Resource;
using Esiur.Core;
using Esiur.Data;
using Esiur.Net.IIP;
namespace Test {
[Public] public enum SizeEnum {
xSmall=-11,
Small=-10,
Medium=0,
Large=1,
XLarge=22
}
}

15
Test/MyChildRecord.cs Normal file
View File

@ -0,0 +1,15 @@
using Esiur.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
[Public]
public class MyChildRecord : MyRecord
{
public string ChildName { get; set; }
}
}

16
Test/MyChildResource.cs Normal file
View File

@ -0,0 +1,16 @@
using Esiur.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test
{
[Resource]
public partial class MyChildResource : MyResource
{
[Public] string childName;
[Public] public int ChildMethod(string childName) => 111;
}
}

View File

@ -1,51 +0,0 @@
using Esiur.Data;
using Esiur.Core;
using Esiur.Resource;
using Esiur.Security.Authority;
using Esiur.Security.Membership;
using System;
using System.Collections.Generic;
using System.Text;
namespace Test
{
public class MyMembership : IMembership
{
public Instance Instance { get; set; }
public event DestroyedEvent OnDestroy;
public void Destroy()
{
}
public AsyncReply<byte[]> GetPassword(string username, string domain)
{
return new AsyncReply<byte[]>(DC.ToBytes("1234"));
}
public AsyncReply<bool> Login(Session session)
{
return new AsyncReply<bool>(true);
}
public AsyncReply<bool> Logout(Session session)
{
return new AsyncReply<bool>(true);
}
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
{
return new AsyncReply<bool>(true);
}
public AsyncReply<bool> UserExists(string username, string domain)
{
return new AsyncReply<bool>(username == "demo");
}
}
}

Some files were not shown because too many files have changed in this diff Show More