mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2025-05-06 03:32:57 +00:00
2.2
This commit is contained in:
parent
530df018ec
commit
9a174f406f
@ -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);
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
10
Esiur.sln
10
Esiur.sln
@ -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
|
||||
|
@ -32,7 +32,7 @@ public class AsyncAwaiter<T> : INotifyCompletion
|
||||
public T GetResult()
|
||||
{
|
||||
if (exception != null)
|
||||
throw exception;
|
||||
throw exception;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
{
|
||||
|
||||
|
@ -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;
|
||||
//
|
||||
}
|
||||
}
|
||||
|
1687
Esiur/Data/Codec.cs
1687
Esiur/Data/Codec.cs
File diff suppressed because it is too large
Load Diff
@ -93,10 +93,10 @@ public static class DC // Data Converter
|
||||
rt.Set(value);
|
||||
return rt;
|
||||
}
|
||||
else if (sourceType == typeof(Structure) && sourceType.IsAssignableFrom(destinationType))
|
||||
{
|
||||
return Structure.FromStructure((Structure)value, destinationType);
|
||||
}
|
||||
//else if (sourceType == typeof(Structure) && sourceType.IsAssignableFrom(destinationType))
|
||||
//{
|
||||
// return Structure.FromStructure((Structure)value, destinationType);
|
||||
//}
|
||||
else if (destinationType.IsEnum)
|
||||
{
|
||||
return Enum.ToObject(destinationType, value);
|
||||
@ -190,45 +190,6 @@ public static class DC // Data Converter
|
||||
return value.ToByteArray();
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(Guid[] value)
|
||||
{
|
||||
var rt = new List<byte>();
|
||||
foreach (var g in value)
|
||||
rt.AddRange(g.ToByteArray());
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(char[] value)
|
||||
{
|
||||
List<byte> rt = new List<byte>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
rt.AddRange(ToBytes(value[i]));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(short[] value)
|
||||
{
|
||||
List<byte> rt = new List<byte>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
rt.AddRange(ToBytes(value[i]));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static byte[] ToBytes(ushort[] value)
|
||||
{
|
||||
List<byte> rt = new List<byte>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
rt.AddRange(ToBytes(value[i]));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static void Append(ref byte[] dst, byte[] src)
|
||||
{
|
||||
@ -265,88 +226,6 @@ public static class DC // Data Converter
|
||||
}
|
||||
|
||||
|
||||
public static byte[] ToBytes(this int[] value)
|
||||
{
|
||||
List<byte> rt = new List<byte>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
rt.AddRange(ToBytes(value[i]));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(this uint[] value)
|
||||
{
|
||||
List<byte> rt = new List<byte>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
rt.AddRange(ToBytes(value[i]));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(this long[] value)
|
||||
{
|
||||
List<byte> rt = new List<byte>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
rt.AddRange(ToBytes(value[i]));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(this ulong[] value)
|
||||
{
|
||||
List<byte> rt = new List<byte>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
rt.AddRange(ToBytes(value[i]));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(this float[] value)
|
||||
{
|
||||
List<byte> rt = new List<byte>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
rt.AddRange(ToBytes(value[i]));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(this double[] value)
|
||||
{
|
||||
List<byte> rt = new List<byte>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
rt.AddRange(ToBytes(value[i]));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] ToBytes(this decimal[] value)
|
||||
{
|
||||
List<byte> rt = new List<byte>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
rt.AddRange(ToBytes(value[i]));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] ToBytes(this DateTime[] value)
|
||||
{
|
||||
List<byte> rt = new List<byte>();
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
rt.AddRange(ToBytes(value[i]));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] ToBytes(this string[] value)
|
||||
{
|
||||
@ -356,7 +235,7 @@ public static class DC // Data Converter
|
||||
{
|
||||
byte[] ba = ToBytes(value[i]);
|
||||
// add string length
|
||||
rt.AddRange(ToBytes(ba.Length));
|
||||
rt.AddRange(ToBytes(ba.Length, Endian.Little));
|
||||
// add encoded string
|
||||
rt.AddRange(ba);
|
||||
}
|
||||
@ -364,41 +243,68 @@ public static class DC // Data Converter
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static unsafe byte[] ToBytes(this int value)
|
||||
|
||||
public static unsafe byte[] ToBytes(this int value, Endian endian)
|
||||
{
|
||||
var rt = new byte[4];
|
||||
byte* p = (byte*)&value;
|
||||
|
||||
rt[0] = *(p + 3);
|
||||
rt[1] = *(p + 2);
|
||||
rt[2] = *(p + 1);
|
||||
rt[3] = *(p + 0);
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = rt)
|
||||
*((int*)ptr) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte* p = (byte*)&value;
|
||||
|
||||
rt[0] = *(p + 3);
|
||||
rt[1] = *(p + 2);
|
||||
rt[2] = *(p + 1);
|
||||
rt[3] = *(p + 0);
|
||||
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static unsafe byte[] ToBytes(this short value)
|
||||
|
||||
|
||||
public static unsafe byte[] ToBytes(this short value, Endian endian)
|
||||
{
|
||||
var rt = new byte[2];
|
||||
byte* p = (byte*)&value;
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = rt)
|
||||
*((short*)ptr) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte* p = (byte*)&value;
|
||||
|
||||
rt[0] = *(p + 1);
|
||||
rt[1] = *(p + 0);
|
||||
rt[0] = *(p + 1);
|
||||
rt[1] = *(p + 0);
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static unsafe byte[] ToBytes(this float value)
|
||||
public static unsafe byte[] ToBytes(this float value, Endian endian)
|
||||
|
||||
{
|
||||
var rt = new byte[4];
|
||||
|
||||
//float rt = 0;
|
||||
byte* p = (byte*)&value;
|
||||
rt[0] = *(p + 3);
|
||||
rt[1] = *(p + 2);
|
||||
rt[2] = *(p + 1);
|
||||
rt[3] = *(p);
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = rt)
|
||||
*((float*)ptr) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte* p = (byte*)&value;
|
||||
rt[0] = *(p + 3);
|
||||
rt[1] = *(p + 2);
|
||||
rt[2] = *(p + 1);
|
||||
rt[3] = *(p);
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
@ -406,122 +312,153 @@ public static class DC // Data Converter
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static byte[] ToBytes(this string value)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(value);
|
||||
}
|
||||
|
||||
public unsafe static byte[] ToBytes(this double value)
|
||||
public unsafe static byte[] ToBytes(this double value, Endian endian)
|
||||
{
|
||||
var rt = new byte[8];
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = rt)
|
||||
*((double*)ptr) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte* p = (byte*)&value;
|
||||
|
||||
byte* p = (byte*)&value;
|
||||
|
||||
rt[0] = *(p + 7);
|
||||
rt[1] = *(p + 6);
|
||||
rt[2] = *(p + 5);
|
||||
rt[3] = *(p + 4);
|
||||
rt[4] = *(p + 3);
|
||||
rt[5] = *(p + 2);
|
||||
rt[6] = *(p + 1);
|
||||
rt[7] = *(p + 0);
|
||||
rt[0] = *(p + 7);
|
||||
rt[1] = *(p + 6);
|
||||
rt[2] = *(p + 5);
|
||||
rt[3] = *(p + 4);
|
||||
rt[4] = *(p + 3);
|
||||
rt[5] = *(p + 2);
|
||||
rt[6] = *(p + 1);
|
||||
rt[7] = *(p + 0);
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static unsafe byte[] ToBytes(this long value)
|
||||
public static unsafe byte[] ToBytes(this long value, Endian endian)
|
||||
{
|
||||
var rt = new byte[8];
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = rt)
|
||||
*((long*)ptr) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte* p = (byte*)&value;
|
||||
|
||||
byte* p = (byte*)&value;
|
||||
|
||||
rt[0] = *(p + 7);
|
||||
rt[1] = *(p + 6);
|
||||
rt[2] = *(p + 5);
|
||||
rt[3] = *(p + 4);
|
||||
rt[4] = *(p + 3);
|
||||
rt[5] = *(p + 2);
|
||||
rt[6] = *(p + 1);
|
||||
rt[7] = *(p + 0);
|
||||
rt[0] = *(p + 7);
|
||||
rt[1] = *(p + 6);
|
||||
rt[2] = *(p + 5);
|
||||
rt[3] = *(p + 4);
|
||||
rt[4] = *(p + 3);
|
||||
rt[5] = *(p + 2);
|
||||
rt[6] = *(p + 1);
|
||||
rt[7] = *(p + 0);
|
||||
}
|
||||
|
||||
return rt;
|
||||
|
||||
}
|
||||
|
||||
public static unsafe byte[] ToBytes(this DateTime value)
|
||||
{
|
||||
|
||||
var rt = new byte[8];
|
||||
var v = value.ToUniversalTime().Ticks;
|
||||
|
||||
byte* p = (byte*)&v;
|
||||
|
||||
rt[0] = *(p + 7);
|
||||
rt[1] = *(p + 6);
|
||||
rt[2] = *(p + 5);
|
||||
rt[3] = *(p + 4);
|
||||
rt[4] = *(p + 3);
|
||||
rt[5] = *(p + 2);
|
||||
rt[6] = *(p + 1);
|
||||
rt[7] = *(p + 0);
|
||||
|
||||
fixed (byte* ptr = rt)
|
||||
*((long*)ptr) = v;
|
||||
return rt;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static unsafe byte[] ToBytes(this ulong value)
|
||||
public static unsafe byte[] ToBytes(this ulong value, Endian endia)
|
||||
{
|
||||
var rt = new byte[8];
|
||||
if (endia == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = rt)
|
||||
*((ulong*)ptr) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
byte* p = (byte*)&value;
|
||||
byte* p = (byte*)&value;
|
||||
|
||||
rt[0] = *(p + 7);
|
||||
rt[1] = *(p + 6);
|
||||
rt[2] = *(p + 5);
|
||||
rt[3] = *(p + 4);
|
||||
rt[4] = *(p + 3);
|
||||
rt[5] = *(p + 2);
|
||||
rt[6] = *(p + 1);
|
||||
rt[7] = *(p + 0);
|
||||
rt[0] = *(p + 7);
|
||||
rt[1] = *(p + 6);
|
||||
rt[2] = *(p + 5);
|
||||
rt[3] = *(p + 4);
|
||||
rt[4] = *(p + 3);
|
||||
rt[5] = *(p + 2);
|
||||
rt[6] = *(p + 1);
|
||||
rt[7] = *(p + 0);
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static unsafe byte[] ToBytes(this uint value)
|
||||
public static unsafe byte[] ToBytes(this uint value, Endian endian)
|
||||
{
|
||||
|
||||
var rt = new byte[4];
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = rt)
|
||||
*((uint*)ptr) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
byte* p = (byte*)&value;
|
||||
byte* p = (byte*)&value;
|
||||
|
||||
rt[0] = *(p + 3);
|
||||
rt[1] = *(p + 2);
|
||||
rt[2] = *(p + 1);
|
||||
rt[3] = *(p + 0);
|
||||
rt[0] = *(p + 3);
|
||||
rt[1] = *(p + 2);
|
||||
rt[2] = *(p + 1);
|
||||
rt[3] = *(p + 0);
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static unsafe byte[] ToBytes(this ushort value)
|
||||
public static unsafe byte[] ToBytes(this ushort value, Endian endian)
|
||||
{
|
||||
var rt = new byte[2];
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = rt)
|
||||
*((ushort*)ptr) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte* p = (byte*)&value;
|
||||
|
||||
byte* p = (byte*)&value;
|
||||
|
||||
rt[0] = *(p + 1);
|
||||
rt[1] = *(p);
|
||||
|
||||
rt[0] = *(p + 1);
|
||||
rt[1] = *(p);
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static byte[] ToBytes(this decimal value)
|
||||
public static unsafe byte[] ToBytes(this decimal value, Endian endian)
|
||||
{
|
||||
byte[] ret = new byte[0];// BitConverter.GetBytes(value);
|
||||
var rt = new byte[16];
|
||||
fixed (byte* ptr = rt)
|
||||
*((decimal*)ptr) = value;
|
||||
|
||||
Array.Reverse(ret);
|
||||
if (endian == Endian.Big)
|
||||
Array.Reverse(rt);
|
||||
|
||||
return ret;
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static string ToHex(this byte[] ba)
|
||||
@ -533,22 +470,10 @@ public static class DC // Data Converter
|
||||
|
||||
public static string ToHex(this byte[] ba, uint offset, uint length, string separator = " ")
|
||||
{
|
||||
|
||||
if (separator == null)
|
||||
separator = "";
|
||||
|
||||
return string.Join(separator, ba.Skip((int)offset).Take((int)length).Select(x => x.ToString("x2")).ToArray());
|
||||
|
||||
//StringBuilder hex = new StringBuilder((int)length * 2);
|
||||
|
||||
//for (var i = offset; i < offset + length; i++)
|
||||
//{
|
||||
// hex.AppendFormat("{0:x2}", ba[i]);
|
||||
// if (separator != null)
|
||||
// hex.Append(separator);
|
||||
//}
|
||||
|
||||
//return hex.ToString();
|
||||
}
|
||||
|
||||
public static byte[] FromHex(string hexString, string separator = " ")
|
||||
@ -639,240 +564,186 @@ public static class DC // Data Converter
|
||||
return (sbyte)data[offset];
|
||||
}
|
||||
|
||||
public static sbyte[] GetInt8Array(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
var rt = new sbyte[length];
|
||||
Buffer.BlockCopy(data, (int)offset, rt, 0, (int)length);
|
||||
return rt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static byte GetUInt8(this byte[] data, uint offset)
|
||||
{
|
||||
return data[offset];
|
||||
}
|
||||
|
||||
public static byte[] GetUInt8Array(this byte[] data, uint offset, uint length)
|
||||
public static unsafe short GetInt16(this byte[] data, uint offset, Endian endian)
|
||||
{
|
||||
var rt = new byte[length];
|
||||
Buffer.BlockCopy(data, (int)offset, rt, 0, (int)length);
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static Int16 GetInt16(this byte[] data, uint offset)
|
||||
{
|
||||
return (Int16)((data[offset] << 8) | data[offset + 1]);
|
||||
}
|
||||
|
||||
public static Int16[] GetInt16Array(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
|
||||
var rt = new Int16[length / 2];
|
||||
for (var i = offset; i < end; i += 2)
|
||||
rt[j++] = GetInt16(data, i);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static UInt16 GetUInt16(this byte[] data, uint offset)
|
||||
{
|
||||
return (UInt16)((data[offset] << 8) | data[offset + 1]);
|
||||
}
|
||||
|
||||
public static UInt16[] GetUInt16Array(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
var rt = new UInt16[length / 2];
|
||||
|
||||
for (var i = offset; i < end; i += 2)
|
||||
rt[j++] = GetUInt16(data, i);
|
||||
|
||||
return rt;
|
||||
|
||||
}
|
||||
|
||||
public static Int32 GetInt32(this byte[] data, uint offset)
|
||||
{
|
||||
return (Int32)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]);
|
||||
}
|
||||
|
||||
public static Int32[] GetInt32Array(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
|
||||
var rt = new Int32[length / 4];
|
||||
for (var i = offset; i < end; i += 4)
|
||||
rt[j++] = GetInt32(data, i);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static UInt32 GetUInt32(this byte[] data, uint offset)
|
||||
{
|
||||
return (UInt32)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]);
|
||||
}
|
||||
|
||||
public static UInt32[] GetUInt32Array(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
var rt = new UInt32[length / 4];
|
||||
|
||||
for (var i = offset; i < end; i += 4)
|
||||
rt[j++] = GetUInt16(data, i);
|
||||
|
||||
return rt;
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return *(short*)ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (Int16)((data[offset] << 8) | data[offset + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static unsafe UInt64 GetUInt64(this byte[] data, uint offset)
|
||||
|
||||
public static unsafe ushort GetUInt16(this byte[] data, uint offset, Endian endian)
|
||||
{
|
||||
UInt64 rt = 0;
|
||||
byte* p = (byte*)&rt;
|
||||
|
||||
*(p + 7) = data[offset++];
|
||||
*(p + 6) = data[offset++];
|
||||
*(p + 5) = data[offset++];
|
||||
*(p + 4) = data[offset++];
|
||||
*(p + 3) = data[offset++];
|
||||
*(p + 2) = data[offset++];
|
||||
*(p + 1) = data[offset++];
|
||||
*(p) = data[offset++];
|
||||
|
||||
return rt;
|
||||
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return *(ushort*)ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (UInt16)((data[offset] << 8) | data[offset + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
public static Int64[] GetInt64Array(this byte[] data, uint offset, uint length)
|
||||
public static unsafe int GetInt32(this byte[] data, uint offset, Endian endian)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
var rt = new Int64[length / 8];
|
||||
|
||||
for (var i = offset; i < end; i += 8)
|
||||
rt[j++] = GetInt64(data, i);
|
||||
|
||||
return rt;
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return *(int*)ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (Int32)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe Int64 GetInt64(this byte[] data, uint offset)
|
||||
public static unsafe uint GetUInt32(this byte[] data, uint offset, Endian endian)
|
||||
{
|
||||
Int64 rt = 0;
|
||||
byte* p = (byte*)&rt;
|
||||
|
||||
*(p + 7) = data[offset++];
|
||||
*(p + 6) = data[offset++];
|
||||
*(p + 5) = data[offset++];
|
||||
*(p + 4) = data[offset++];
|
||||
*(p + 3) = data[offset++];
|
||||
*(p + 2) = data[offset++];
|
||||
*(p + 1) = data[offset++];
|
||||
*(p) = data[offset++];
|
||||
|
||||
return rt;
|
||||
|
||||
/* Or
|
||||
return (Int64)(
|
||||
(data[offset] << 56)
|
||||
| (data[offset + 1] << 48)
|
||||
| (data[offset + 2] << 40)
|
||||
| (data[offset + 3] << 32)
|
||||
| (data[offset + 4] << 24)
|
||||
| (data[offset + 5] << 16)
|
||||
| (data[offset + 6] << 8)
|
||||
| (data[offset + 7])
|
||||
);
|
||||
*/
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return *(uint*)ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (uint)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
public static UInt64[] GetUInt64Array(this byte[] data, uint offset, uint length)
|
||||
|
||||
|
||||
|
||||
public static unsafe ulong GetUInt64(this byte[] data, uint offset, Endian endian)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
var rt = new UInt64[length / 8];
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return *(ulong*)ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt64 rt = 0;
|
||||
byte* p = (byte*)&rt;
|
||||
|
||||
for (var i = offset; i < end; i += 8)
|
||||
rt[j++] = GetUInt64(data, i);
|
||||
*(p + 7) = data[offset++];
|
||||
*(p + 6) = data[offset++];
|
||||
*(p + 5) = data[offset++];
|
||||
*(p + 4) = data[offset++];
|
||||
*(p + 3) = data[offset++];
|
||||
*(p + 2) = data[offset++];
|
||||
*(p + 1) = data[offset++];
|
||||
*(p) = data[offset++];
|
||||
|
||||
return rt;
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe float GetFloat32(this byte[] data, uint offset)
|
||||
|
||||
public static unsafe long GetInt64(this byte[] data, uint offset, Endian endian)
|
||||
{
|
||||
float rt = 0;
|
||||
byte* p = (byte*)&rt;
|
||||
*p = data[offset + 3];
|
||||
*(p + 1) = data[offset + 2];
|
||||
*(p + 2) = data[offset + 1];
|
||||
*(p + 3) = data[offset];
|
||||
return rt;
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return *(long*)ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
Int64 rt = 0;
|
||||
byte* p = (byte*)&rt;
|
||||
|
||||
*(p + 7) = data[offset++];
|
||||
*(p + 6) = data[offset++];
|
||||
*(p + 5) = data[offset++];
|
||||
*(p + 4) = data[offset++];
|
||||
*(p + 3) = data[offset++];
|
||||
*(p + 2) = data[offset++];
|
||||
*(p + 1) = data[offset++];
|
||||
*(p) = data[offset++];
|
||||
|
||||
return rt;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static float[] GetFloat32Array(this byte[] data, uint offset, uint length)
|
||||
public static unsafe float GetFloat32(this byte[] data, uint offset, Endian endian)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
var rt = new float[length / 4];
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return *(float*)ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
float rt = 0;
|
||||
byte* p = (byte*)&rt;
|
||||
*p = data[offset + 3];
|
||||
*(p + 1) = data[offset + 2];
|
||||
*(p + 2) = data[offset + 1];
|
||||
*(p + 3) = data[offset];
|
||||
return rt;
|
||||
|
||||
for (var i = offset; i < end; i += 4)
|
||||
rt[j++] = GetFloat32(data, i);
|
||||
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe double GetFloat64(this byte[] data, uint offset)
|
||||
|
||||
public static unsafe double GetFloat64(this byte[] data, uint offset, Endian endian)
|
||||
{
|
||||
double rt = 0;
|
||||
byte* p = (byte*)&rt;
|
||||
if (endian == Endian.Little)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return *(double*)ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
double rt = 0;
|
||||
byte* p = (byte*)&rt;
|
||||
|
||||
*(p + 7) = data[offset++];
|
||||
*(p + 6) = data[offset++];
|
||||
*(p + 5) = data[offset++];
|
||||
*(p + 4) = data[offset++];
|
||||
*(p + 3) = data[offset++];
|
||||
*(p + 2) = data[offset++];
|
||||
*(p + 1) = data[offset++];
|
||||
*(p) = data[offset++];
|
||||
*(p + 7) = data[offset++];
|
||||
*(p + 6) = data[offset++];
|
||||
*(p + 5) = data[offset++];
|
||||
*(p + 4) = data[offset++];
|
||||
*(p + 3) = data[offset++];
|
||||
*(p + 2) = data[offset++];
|
||||
*(p + 1) = data[offset++];
|
||||
*(p) = data[offset++];
|
||||
|
||||
return rt;
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
|
||||
public static double[] GetFloat64Array(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
var rt = new double[length / 8];
|
||||
|
||||
for (var i = offset; i < end; i += 8)
|
||||
rt[j++] = GetFloat64(data, i);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static bool GetBoolean(this byte[] data, uint offset)
|
||||
{
|
||||
return data[offset] > 0;
|
||||
}
|
||||
|
||||
public static bool[] GetBooleanArray(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
var rt = new bool[length];
|
||||
for (var i = 0; i < length; i++)
|
||||
rt[i] = data[offset + i] > 0;
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static char GetChar(this byte[] data, uint offset)
|
||||
{
|
||||
return Convert.ToChar(((data[offset] << 8) | data[offset + 1]));
|
||||
}
|
||||
|
||||
public static char[] GetCharArray(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
|
||||
var j = 0; var end = offset + length;
|
||||
var rt = new char[length / 2];
|
||||
|
||||
for (var i = offset; i < end; i += 2)
|
||||
rt[j++] = GetChar(data, i);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static string GetString(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
@ -887,7 +758,7 @@ public static class DC // Data Converter
|
||||
|
||||
while (i < length)
|
||||
{
|
||||
var cl = GetUInt32(data, offset + i);
|
||||
var cl = GetUInt32(data, offset + i, Endian.Little);
|
||||
i += 4;
|
||||
ar.Add(Encoding.UTF8.GetString(data, (int)(offset + i), (int)cl));
|
||||
i += cl;
|
||||
@ -901,69 +772,24 @@ public static class DC // Data Converter
|
||||
return new Guid(Clip(data, offset, 16));
|
||||
}
|
||||
|
||||
public static Guid[] GetGuidArray(this byte[] data, uint offset, uint length)
|
||||
public static DateTime GetDateTime(this byte[] data, uint offset, Endian endian)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
var rt = new Guid[length / 16];
|
||||
|
||||
for (var i = offset; i < end; i += 16)
|
||||
rt[j++] = GetGuid(data, i);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static DateTime GetDateTime(this byte[] data, uint offset)
|
||||
{
|
||||
var ticks = GetInt64(data, offset);
|
||||
var ticks = GetInt64(data, offset, endian);
|
||||
return new DateTime(ticks, DateTimeKind.Utc);
|
||||
}
|
||||
|
||||
public static DateTime[] GetDateTimeArray(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
var rt = new DateTime[length / 8];
|
||||
|
||||
for (var i = offset; i < end; i += 8)
|
||||
rt[j++] = GetDateTime(data, i);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static IPAddress GetIPv4Address(this byte[] data, uint offset)
|
||||
{
|
||||
return new IPAddress((long)GetUInt32(data, offset));
|
||||
return new IPAddress((long)GetUInt32(data, offset, Endian.Little));
|
||||
}
|
||||
|
||||
public static IPAddress[] GetIPv4AddressArray(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
var rt = new IPAddress[length / 4];
|
||||
|
||||
for (var i = offset; i < end; i += 4)
|
||||
rt[j++] = GetIPv6Address(data, i);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static IPAddress GetIPv6Address(this byte[] data, uint offset)
|
||||
{
|
||||
return new IPAddress(Clip(data, offset, 16));
|
||||
}
|
||||
|
||||
public static IPAddress[] GetIPv6AddressArray(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
var j = 0; var end = offset + length;
|
||||
var rt = new IPAddress[length / 16];
|
||||
|
||||
for (var i = offset; i < end; i += 16)
|
||||
rt[j++] = GetIPv6Address(data, i);
|
||||
|
||||
return rt;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static byte[] Clip(this byte[] data, uint offset, uint length)
|
||||
{
|
||||
if (data.Length < offset + length)
|
||||
|
554
Esiur/Data/DataDeserializer.cs
Normal file
554
Esiur/Data/DataDeserializer.cs
Normal file
@ -0,0 +1,554 @@
|
||||
using Esiur.Core;
|
||||
using Esiur.Net.IIP;
|
||||
using Esiur.Resource;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Esiur.Data;
|
||||
using Esiur.Resource.Template;
|
||||
using System.Linq;
|
||||
|
||||
namespace Esiur.Data;
|
||||
|
||||
public static class DataDeserializer
|
||||
{
|
||||
public static AsyncReply NullParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
return new AsyncReply(null);
|
||||
}
|
||||
|
||||
public static AsyncReply BooleanTrueParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
return new AsyncReply<bool>(true);
|
||||
}
|
||||
|
||||
public static AsyncReply BooleanFalseParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
return new AsyncReply<bool>(false);
|
||||
}
|
||||
|
||||
public static AsyncReply NotModifiedParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
return new AsyncReply<NotModified>(new NotModified());
|
||||
}
|
||||
|
||||
public static AsyncReply ByteParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
return new AsyncReply<byte>(data[offset]);
|
||||
}
|
||||
public static AsyncReply SByteParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
return new AsyncReply<sbyte>((sbyte)data[offset]);
|
||||
}
|
||||
public static unsafe AsyncReply Char16Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<char>(*(char*)ptr);
|
||||
}
|
||||
|
||||
public static AsyncReply Char8Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
return new AsyncReply<char>((char)data[offset]);
|
||||
}
|
||||
|
||||
|
||||
public static unsafe AsyncReply Int16Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<short>(*(short*)ptr);
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply UInt16Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<ushort>(*(ushort*)ptr);
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply Int32Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<int>(*(int*)ptr);
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply UInt32Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<uint>(*(uint*)ptr);
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply Float32Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<float>(*(float*)ptr);
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply Float64Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<double>(*(double*)ptr);
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply Float128Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<decimal>(*(decimal*)ptr);
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply Int128Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<decimal>(*(decimal*)ptr);
|
||||
}
|
||||
|
||||
|
||||
public static unsafe AsyncReply UInt128Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<decimal>(*(decimal*)ptr);
|
||||
}
|
||||
|
||||
|
||||
public static unsafe AsyncReply Int64Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<long>(*(long*)ptr);
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply UInt64Parser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<ulong>(*(ulong*)ptr);
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply DateTimeParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return new AsyncReply<DateTime>(new DateTime(*(long*)ptr, DateTimeKind.Utc));
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static unsafe AsyncReply ResourceParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return connection.Fetch(*(uint*)ptr);
|
||||
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply LocalResourceParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
fixed (byte* ptr = &data[offset])
|
||||
return Warehouse.GetById(*(uint*)ptr);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static unsafe AsyncReply RawDataParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
return new AsyncReply<byte[]>(data.Clip(offset, length));
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply StringParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
return new AsyncReply<string>(data.GetString(offset, length));
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply RecordParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
|
||||
var reply = new AsyncReply<IRecord>();
|
||||
|
||||
var classId = data.GetGuid(offset);
|
||||
offset += 16;
|
||||
length -= 16;
|
||||
|
||||
|
||||
var template = Warehouse.GetTemplateByClassId((Guid)classId, TemplateType.Record);
|
||||
|
||||
if (template != null)
|
||||
{
|
||||
//ListParser(data, offset, length, connection)
|
||||
ListParser(data, offset, length, connection).Then(r =>
|
||||
{
|
||||
var ar = (object[])r;
|
||||
|
||||
if (template.DefinedType != null)
|
||||
{
|
||||
var record = Activator.CreateInstance(template.DefinedType) as IRecord;
|
||||
for (var i = 0; i < template.Properties.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var v = Convert.ChangeType(ar[i], template.Properties[i].PropertyInfo.PropertyType);
|
||||
template.Properties[i].PropertyInfo.SetValue(record, v);
|
||||
} catch ( Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
reply.Trigger(record);
|
||||
}
|
||||
else
|
||||
{
|
||||
var record = new Record();
|
||||
|
||||
for (var i = 0; i < template.Properties.Length; i++)
|
||||
record.Add(template.Properties[i].Name, ar[i]);
|
||||
|
||||
reply.Trigger(record);
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
connection.GetTemplate((Guid)classId).Then(tmp =>
|
||||
{
|
||||
ListParser(data, offset, length, connection).Then(r =>
|
||||
{
|
||||
var ar = (object[])r;
|
||||
|
||||
var record = new Record();
|
||||
|
||||
for (var i = 0; i < tmp.Properties.Length; i++)
|
||||
record.Add(tmp.Properties[i].Name, ar[i]);
|
||||
|
||||
reply.Trigger(record);
|
||||
});
|
||||
}).Error(x => reply.TriggerError(x));
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply ConstantParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static unsafe AsyncReply EnumParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
|
||||
var classId = data.GetGuid(offset);
|
||||
offset += 16;
|
||||
var index = data[offset++];
|
||||
|
||||
var template = Warehouse.GetTemplateByClassId((Guid)classId, TemplateType.Enum);
|
||||
|
||||
if (template != null)
|
||||
{
|
||||
return new AsyncReply(template.Constants[index].Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var reply = new AsyncReply();
|
||||
|
||||
connection.GetTemplate((Guid)classId).Then(tmp =>
|
||||
{
|
||||
reply.Trigger(tmp.Constants[index].Value);
|
||||
}).Error(x => reply.TriggerError(x));
|
||||
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static AsyncReply RecordListParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
var rt = new AsyncBag<IRecord>();
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
var (cs, reply) = Codec.Parse(data, offset, connection);
|
||||
|
||||
rt.Add(reply);
|
||||
|
||||
if (cs > 0)
|
||||
{
|
||||
offset += (uint)cs;
|
||||
length -= (uint)cs;
|
||||
}
|
||||
else
|
||||
throw new Exception("Error while parsing structured data");
|
||||
|
||||
}
|
||||
|
||||
rt.Seal();
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static AsyncReply ResourceListParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
var rt = new AsyncBag<IResource>();
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
var (cs, reply) = Codec.Parse(data, offset, connection);
|
||||
|
||||
rt.Add(reply);
|
||||
|
||||
if (cs > 0)
|
||||
{
|
||||
offset += (uint)cs;
|
||||
length -= (uint)cs;
|
||||
}
|
||||
else
|
||||
throw new Exception("Error while parsing structured data");
|
||||
|
||||
}
|
||||
|
||||
rt.Seal();
|
||||
return rt;
|
||||
}
|
||||
|
||||
|
||||
public static AsyncBag<object> ListParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
var rt = new AsyncBag<object>();
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
var (cs, reply) = Codec.Parse(data, offset, connection);
|
||||
|
||||
rt.Add(reply);
|
||||
|
||||
if (cs > 0)
|
||||
{
|
||||
offset += (uint)cs;
|
||||
length -= (uint)cs;
|
||||
}
|
||||
else
|
||||
throw new Exception("Error while parsing structured data");
|
||||
|
||||
}
|
||||
|
||||
rt.Seal();
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static AsyncReply TypedMapParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
// get key type
|
||||
var (keyCs, keyRepType) = RepresentationType.Parse(data, offset);
|
||||
offset += keyCs;
|
||||
length -= keyCs;
|
||||
|
||||
var (valueCs, valueRepType) = RepresentationType.Parse(data, offset);
|
||||
offset += valueCs;
|
||||
length -= valueCs;
|
||||
|
||||
var map = (IMap)Activator.CreateInstance(typeof(Map<,>).MakeGenericType(keyRepType.GetRuntimeType(), valueRepType.GetRuntimeType()));
|
||||
|
||||
var rt = new AsyncReply();
|
||||
|
||||
var results = new AsyncBag<object>();
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
var (cs, reply) = Codec.Parse(data, offset, connection);
|
||||
|
||||
|
||||
results.Add(reply);
|
||||
|
||||
if (cs > 0)
|
||||
{
|
||||
offset += (uint)cs;
|
||||
length -= (uint)cs;
|
||||
}
|
||||
else
|
||||
throw new Exception("Error while parsing structured data");
|
||||
|
||||
}
|
||||
|
||||
results.Seal();
|
||||
|
||||
results.Then(ar =>
|
||||
{
|
||||
for (var i = 0; i < ar.Length; i += 2)
|
||||
map.Add(ar[i], ar[i + 1]);
|
||||
|
||||
rt.Trigger(map);
|
||||
});
|
||||
|
||||
|
||||
return rt;
|
||||
|
||||
}
|
||||
|
||||
public static AsyncReply TupleParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
var results = new AsyncBag<object>();
|
||||
var rt = new AsyncReply();
|
||||
|
||||
var tupleSize = data[offset++];
|
||||
length--;
|
||||
|
||||
var types = new List<Type>();
|
||||
|
||||
for (var i = 0; i < tupleSize; i++)
|
||||
{
|
||||
var (cs, rep) = RepresentationType.Parse(data, offset);
|
||||
types.Add(rep.GetRuntimeType());
|
||||
offset += cs;
|
||||
length -= cs;
|
||||
}
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
var (cs, reply) = Codec.Parse(data, offset, connection);
|
||||
|
||||
results.Add(reply);
|
||||
|
||||
if (cs > 0)
|
||||
{
|
||||
offset += (uint)cs;
|
||||
length -= (uint)cs;
|
||||
}
|
||||
else
|
||||
throw new Exception("Error while parsing structured data");
|
||||
|
||||
}
|
||||
|
||||
results.Seal();
|
||||
|
||||
|
||||
results.Then(ar =>
|
||||
{
|
||||
if (ar.Length == 2)
|
||||
{
|
||||
var type = typeof(ValueTuple<,>).MakeGenericType(types.ToArray());
|
||||
rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1]));
|
||||
}
|
||||
else if (ar.Length == 3)
|
||||
{
|
||||
var type = typeof(ValueTuple<,,>).MakeGenericType(types.ToArray());
|
||||
rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2]));
|
||||
}
|
||||
else if (ar.Length == 4)
|
||||
{
|
||||
var type = typeof(ValueTuple<,,,>).MakeGenericType(types.ToArray());
|
||||
rt.Trigger(Activator.CreateInstance(type, ar[0], ar[1], ar[2], ar[3]));
|
||||
}
|
||||
});
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static AsyncReply TypedListParser(byte[] data, uint offset, uint length, DistributedConnection connection)
|
||||
{
|
||||
var rt = new AsyncBag<object>();
|
||||
|
||||
// get the type
|
||||
var (hdrCs, rep) = RepresentationType.Parse(data, offset);
|
||||
|
||||
offset += hdrCs;
|
||||
length -= hdrCs;
|
||||
|
||||
var runtimeType = rep.GetRuntimeType();
|
||||
|
||||
rt.ArrayType = runtimeType;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
var (cs, reply) = Codec.Parse(data, offset, connection);
|
||||
|
||||
rt.Add(reply);
|
||||
|
||||
if (cs > 0)
|
||||
{
|
||||
offset += (uint)cs;
|
||||
length -= (uint)cs;
|
||||
}
|
||||
else
|
||||
throw new Exception("Error while parsing structured data");
|
||||
|
||||
}
|
||||
|
||||
rt.Seal();
|
||||
return rt;
|
||||
}
|
||||
|
||||
|
||||
public static AsyncBag<PropertyValue> PropertyValueArrayParser(byte[] data, uint offset, uint length, DistributedConnection connection)//, bool ageIncluded = true)
|
||||
{
|
||||
var rt = new AsyncBag<PropertyValue>();
|
||||
|
||||
|
||||
ListParser(data, offset, length, connection).Then(x =>
|
||||
{
|
||||
var ar = (object[])x;
|
||||
var pvs = new List<PropertyValue>();
|
||||
|
||||
for (var i = 0; i < ar.Length; i += 3)
|
||||
pvs.Add(new PropertyValue(ar[2], (ulong?)ar[0], (DateTime?)ar[1]));
|
||||
|
||||
|
||||
rt.Trigger(pvs.ToArray());
|
||||
});
|
||||
|
||||
return rt;
|
||||
|
||||
}
|
||||
|
||||
public static (uint, AsyncReply<PropertyValue>) PropertyValueParser(byte[] data, uint offset, DistributedConnection connection)//, bool ageIncluded = true)
|
||||
{
|
||||
var reply = new AsyncReply<PropertyValue>();
|
||||
|
||||
var age = data.GetUInt64(offset, Endian.Little);
|
||||
offset += 8;
|
||||
|
||||
DateTime date = data.GetDateTime(offset, Endian.Little);
|
||||
offset += 8;
|
||||
|
||||
|
||||
var (valueSize, results) = Codec.Parse(data, offset, connection);
|
||||
|
||||
results.Then(value =>
|
||||
{
|
||||
reply.Trigger(new PropertyValue(value, age, date));
|
||||
});
|
||||
|
||||
return (16 + valueSize, reply);
|
||||
}
|
||||
|
||||
public static AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>> HistoryParser(byte[] data, uint offset, uint length, IResource resource, DistributedConnection connection)
|
||||
{
|
||||
//var count = (int)toAge - (int)fromAge;
|
||||
|
||||
var list = new KeyList<PropertyTemplate, PropertyValue[]>();
|
||||
|
||||
var reply = new AsyncReply<KeyList<PropertyTemplate, PropertyValue[]>>();
|
||||
|
||||
var bagOfBags = new AsyncBag<PropertyValue[]>();
|
||||
|
||||
var ends = offset + length;
|
||||
while (offset < ends)
|
||||
{
|
||||
var index = data[offset++];
|
||||
var pt = resource.Instance.Template.GetPropertyTemplateByIndex(index);
|
||||
list.Add(pt, null);
|
||||
var cs = data.GetUInt32(offset, Endian.Little);
|
||||
offset += 4;
|
||||
|
||||
var (len, pv) = PropertyValueParser(data, offset, connection);
|
||||
|
||||
bagOfBags.Add(pv);// ParsePropertyValueArray(data, offset, cs, connection));
|
||||
offset += len;
|
||||
}
|
||||
|
||||
bagOfBags.Seal();
|
||||
|
||||
bagOfBags.Then(x =>
|
||||
{
|
||||
for (var i = 0; i < list.Count; i++)
|
||||
list[list.Keys.ElementAt(i)] = x[i];
|
||||
|
||||
reply.Trigger(list);
|
||||
});
|
||||
|
||||
return reply;
|
||||
|
||||
}
|
||||
|
||||
}
|
416
Esiur/Data/DataSerializer.cs
Normal file
416
Esiur/Data/DataSerializer.cs
Normal file
@ -0,0 +1,416 @@
|
||||
using Esiur.Core;
|
||||
using Esiur.Net.IIP;
|
||||
using Esiur.Resource;
|
||||
using Esiur.Resource.Template;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Data;
|
||||
|
||||
public static class DataSerializer
|
||||
{
|
||||
public delegate byte[] Serializer(object value);
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) Int32Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
var v = (int)value;
|
||||
var rt = new byte[4];
|
||||
fixed (byte* ptr = rt)
|
||||
*((int*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.Int32, rt);
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) UInt32Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
var v = (uint)value;
|
||||
var rt = new byte[4];
|
||||
fixed (byte* ptr = rt)
|
||||
*((uint*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.UInt32, rt);
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) Int16Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
var v = (short)value;
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((short*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.Int16, rt);
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) UInt16Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
var v = (ushort)value;
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((ushort*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.UInt16, rt);
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) Float32Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
var v = (float)value;
|
||||
var rt = new byte[4];
|
||||
fixed (byte* ptr = rt)
|
||||
*((float*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.Float32, rt);
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) Float64Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
var v = (double)value;
|
||||
var rt = new byte[8];
|
||||
fixed (byte* ptr = rt)
|
||||
*((double*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.Float64, rt);
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) Int64Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
var v = (long)value;
|
||||
var rt = new byte[8];
|
||||
fixed (byte* ptr = rt)
|
||||
*((long*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.Int64, rt);
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) UIn64Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
var v = (ulong)value;
|
||||
var rt = new byte[8];
|
||||
fixed (byte* ptr = rt)
|
||||
*((ulong*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.UInt64, rt);
|
||||
}
|
||||
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) DateTimeComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
var v = ((DateTime)value).ToUniversalTime().Ticks;
|
||||
var rt = new byte[8];
|
||||
fixed (byte* ptr = rt)
|
||||
*((long*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.DateTime, rt);
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) Float128Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
var v = (decimal)value;
|
||||
var rt = new byte[16];
|
||||
fixed (byte* ptr = rt)
|
||||
*((decimal*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.Float128, rt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) StringComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
return (TransmissionTypeIdentifier.String, Encoding.UTF8.GetBytes((string)value));
|
||||
}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) EnumComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
if (value == null)
|
||||
return (TransmissionTypeIdentifier.Null, new byte[0]);
|
||||
|
||||
var template = Warehouse.GetTemplateByType(value.GetType());
|
||||
|
||||
var intVal = Convert.ChangeType(value, (value as Enum).GetTypeCode());
|
||||
|
||||
var ct = template.Constants.FirstOrDefault(x => x.Value.Equals(intVal));
|
||||
|
||||
if (ct == null)
|
||||
return (TransmissionTypeIdentifier.Null, new byte[0]);
|
||||
|
||||
|
||||
var rt = new List<byte>();
|
||||
rt.AddRange(template.ClassId.ToByteArray());
|
||||
rt.Add(ct.Index);
|
||||
|
||||
return (TransmissionTypeIdentifier.Enum, rt.ToArray());
|
||||
}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) UInt8Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
return (TransmissionTypeIdentifier.UInt8, new byte[] { (byte)value });
|
||||
}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) Int8Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
return (TransmissionTypeIdentifier.Int8, new byte[] { (byte)(sbyte)value });
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) Char8Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
return (TransmissionTypeIdentifier.Char8, new byte[] { (byte)(char)value });
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) Char16Composer(object value, DistributedConnection connection)
|
||||
{
|
||||
|
||||
var v = (char)value;
|
||||
var rt = new byte[2];
|
||||
fixed (byte* ptr = rt)
|
||||
*((char*)ptr) = v;
|
||||
return (TransmissionTypeIdentifier.Char16, rt);
|
||||
|
||||
}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) BoolComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
return ((bool)value ? TransmissionTypeIdentifier.True : TransmissionTypeIdentifier.False, new byte[0]);
|
||||
}
|
||||
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) NotModifiedComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
return (TransmissionTypeIdentifier.NotModified, new byte[0]);
|
||||
}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) RawDataComposerFromArray(object value, DistributedConnection connection)
|
||||
{
|
||||
return (TransmissionTypeIdentifier.RawData, (byte[])value);
|
||||
}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) RawDataComposerFromList(dynamic value, DistributedConnection connection)
|
||||
{
|
||||
return (TransmissionTypeIdentifier.RawData, (value as List<byte>).ToArray());
|
||||
}
|
||||
|
||||
//public static (TransmissionTypeIdentifier, byte[]) ListComposerFromArray(dynamic value, DistributedConnection connection)
|
||||
//{
|
||||
// var rt = new List<byte>();
|
||||
// var array = (object[])value;
|
||||
|
||||
// for (var i = 0; i < array.Length; i++)
|
||||
// rt.AddRange(Codec.Compose(array[i], connection));
|
||||
|
||||
// return (TransmissionTypeIdentifier.List, rt.ToArray());
|
||||
//}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) ListComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
|
||||
var rt = ArrayComposer((IEnumerable)value, connection);
|
||||
|
||||
if (rt == null)
|
||||
return (TransmissionTypeIdentifier.Null, new byte[0]);
|
||||
else
|
||||
return (TransmissionTypeIdentifier.List, rt);
|
||||
|
||||
|
||||
//var rt = new List<byte>();
|
||||
//var list = (IEnumerable)value;// ((List<object>)value);
|
||||
|
||||
//foreach (var o in list)
|
||||
// rt.AddRange(Codec.Compose(o, connection));
|
||||
|
||||
//return (TransmissionTypeIdentifier.List, rt.ToArray());
|
||||
}
|
||||
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) TypedListComposer(IEnumerable value, Type type, DistributedConnection connection)
|
||||
{
|
||||
var composed = ArrayComposer((IEnumerable)value, connection);
|
||||
|
||||
if (composed == null)
|
||||
return (TransmissionTypeIdentifier.Null, new byte[0]);
|
||||
|
||||
var header = RepresentationType.FromType(type).Compose();
|
||||
|
||||
var rt = new List<byte>();
|
||||
|
||||
rt.AddRange(header);
|
||||
rt.AddRange(composed);
|
||||
|
||||
return (TransmissionTypeIdentifier.TypedList, rt.ToArray());
|
||||
}
|
||||
|
||||
//public static byte[] PropertyValueComposer(PropertyValue propertyValue, DistributedConnection connection)//, bool includeAge = true)
|
||||
//{
|
||||
// var rt = new BinaryList();
|
||||
|
||||
// return
|
||||
// .AddUInt64(propertyValue.Age)
|
||||
// .AddDateTime(propertyValue.Date)
|
||||
// .AddUInt8Array(Codec.Compose(propertyValue.Value, connection))
|
||||
// .ToArray();
|
||||
//}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) PropertyValueArrayComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
if (value == null)
|
||||
return (TransmissionTypeIdentifier.Null, new byte[0]);
|
||||
|
||||
var rt = new List<byte>();
|
||||
var ar = value as PropertyValue[];
|
||||
|
||||
foreach (var pv in ar)
|
||||
{
|
||||
rt.AddRange(Codec.Compose(pv.Age, connection));
|
||||
rt.AddRange(Codec.Compose(pv.Date, connection));
|
||||
rt.AddRange(Codec.Compose(pv.Value, connection));
|
||||
}
|
||||
|
||||
return (TransmissionTypeIdentifier.List, rt.ToArray());
|
||||
}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) TypedMapComposer(object value, Type keyType, Type valueType, DistributedConnection connection)
|
||||
{
|
||||
if (value == null)
|
||||
return (TransmissionTypeIdentifier.Null, new byte[0]);
|
||||
|
||||
var kt = RepresentationType.FromType(keyType).Compose();
|
||||
var vt = RepresentationType.FromType(valueType).Compose();
|
||||
|
||||
var rt = new List<byte>();
|
||||
|
||||
rt.AddRange(kt);
|
||||
rt.AddRange(vt);
|
||||
|
||||
var map = (IMap)value;
|
||||
|
||||
foreach(var el in map.Serialize())
|
||||
rt.AddRange(Codec.Compose(el, connection));
|
||||
|
||||
return (TransmissionTypeIdentifier.TypedMap, rt.ToArray());
|
||||
}
|
||||
|
||||
public static byte[] ArrayComposer(IEnumerable value, DistributedConnection connection)
|
||||
{
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
var rt = new List<byte>();
|
||||
|
||||
foreach (var i in value)
|
||||
rt.AddRange(Codec.Compose(i, connection));
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) ResourceListComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
if (value == null)
|
||||
return (TransmissionTypeIdentifier.Null, new byte[0]);
|
||||
|
||||
|
||||
return (TransmissionTypeIdentifier.ResourceList, ArrayComposer((IEnumerable)value, connection));
|
||||
}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) RecordListComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
if (value == null)
|
||||
return (TransmissionTypeIdentifier.Null, new byte[0]);
|
||||
|
||||
|
||||
return (TransmissionTypeIdentifier.RecordList, ArrayComposer((IEnumerable)value, connection));
|
||||
}
|
||||
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) ResourceComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
var resource = (IResource)value;
|
||||
var rt = new byte[4];
|
||||
|
||||
if (Codec.IsLocalResource(resource, connection))
|
||||
{
|
||||
|
||||
fixed (byte* ptr = rt)
|
||||
*((uint*)ptr) = (resource as DistributedResource).Id;
|
||||
|
||||
return (TransmissionTypeIdentifier.ResourceLocal, rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
//rt.Append((value as IResource).Instance.Template.ClassId, (value as IResource).Instance.Id);
|
||||
connection.cache.Add(value as IResource, DateTime.UtcNow);
|
||||
|
||||
fixed (byte* ptr = rt)
|
||||
*((uint*)ptr) = resource.Instance.Id;
|
||||
|
||||
return (TransmissionTypeIdentifier.Resource, rt);
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) MapComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
if (value == null)
|
||||
return (TransmissionTypeIdentifier.Null, new byte[0]);
|
||||
|
||||
var rt = new List<byte>();
|
||||
var map = (IMap)value;
|
||||
|
||||
foreach (var el in map.Serialize())
|
||||
rt.AddRange(Codec.Compose(el, connection));
|
||||
|
||||
return (TransmissionTypeIdentifier.Map, rt.ToArray());
|
||||
}
|
||||
|
||||
public static unsafe (TransmissionTypeIdentifier, byte[]) RecordComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
var rt = new List<byte>();// BinaryList();
|
||||
var record = (IRecord)value;
|
||||
|
||||
var template = Warehouse.GetTemplateByType(record.GetType());
|
||||
|
||||
|
||||
rt.AddRange(template.ClassId.ToByteArray());
|
||||
|
||||
foreach (var pt in template.Properties)
|
||||
{
|
||||
var propValue = pt.PropertyInfo.GetValue(record, null);
|
||||
rt.AddRange(Codec.Compose(propValue, connection));
|
||||
}
|
||||
|
||||
return (TransmissionTypeIdentifier.Record, rt.ToArray());
|
||||
}
|
||||
public static byte[] HistoryComposer(KeyList<PropertyTemplate, PropertyValue[]> history,
|
||||
DistributedConnection connection, bool prependLength = false)
|
||||
{
|
||||
//@TODO:Test
|
||||
var rt = new BinaryList();
|
||||
|
||||
for (var i = 0; i < history.Count; i++)
|
||||
rt.AddUInt8(history.Keys.ElementAt(i).Index)
|
||||
.AddUInt8Array(Codec.Compose(history.Values.ElementAt(i), connection));
|
||||
|
||||
if (prependLength)
|
||||
rt.InsertInt32(0, rt.Length);
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public static (TransmissionTypeIdentifier, byte[]) TupleComposer(object value, DistributedConnection connection)
|
||||
{
|
||||
if (value == null)
|
||||
return (TransmissionTypeIdentifier.Null, new byte[0]);
|
||||
|
||||
var rt = new List<byte>();
|
||||
|
||||
var fields = value.GetType().GetFields();
|
||||
var list = fields.Select(x => x.GetValue(value)).ToArray();
|
||||
var types = fields.Select(x => RepresentationType.FromType(x.FieldType).Compose()).ToArray();
|
||||
|
||||
rt.Add((byte)list.Length);
|
||||
|
||||
foreach (var t in types)
|
||||
rt.AddRange(t);
|
||||
|
||||
var composed = ArrayComposer(list, connection);
|
||||
|
||||
if (composed == null)
|
||||
return (TransmissionTypeIdentifier.Null, new byte[0]);
|
||||
else
|
||||
{
|
||||
rt.AddRange(composed);
|
||||
return (TransmissionTypeIdentifier.Tuple, rt.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
12
Esiur/Data/Endian.cs
Normal file
12
Esiur/Data/Endian.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Data
|
||||
{
|
||||
public enum Endian
|
||||
{
|
||||
Big,
|
||||
Little
|
||||
}
|
||||
}
|
@ -229,7 +229,7 @@ public class KeyList<KT, T> : IEnumerable<KeyValuePair<KT, T>>
|
||||
#if NETSTANDARD
|
||||
removableList = (typeof(IDestructible).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()));
|
||||
#else
|
||||
removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T)));
|
||||
removableList = (typeof(IDestructible).IsAssignableFrom(typeof(T)));
|
||||
#endif
|
||||
|
||||
this.Owner = owner;
|
||||
|
248
Esiur/Data/Map.cs
Normal file
248
Esiur/Data/Map.cs
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2017 Ahmed Kh. Zamil
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Esiur.Data;
|
||||
using Esiur.Misc;
|
||||
using Esiur.Core;
|
||||
using System.Reflection;
|
||||
using System.Dynamic;
|
||||
|
||||
namespace Esiur.Data;
|
||||
|
||||
//public class Map : IEnumerable<KeyValuePair<object, object>>
|
||||
//{
|
||||
// private Dictionary<object, object> dic = new();
|
||||
|
||||
// public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
|
||||
// {
|
||||
// return dic.GetEnumerator();
|
||||
// }
|
||||
|
||||
// IEnumerator IEnumerable.GetEnumerator()
|
||||
// {
|
||||
// return dic.GetEnumerator();
|
||||
// }
|
||||
//}
|
||||
|
||||
public interface IMap
|
||||
{
|
||||
public void Add(object key, object value);
|
||||
public void Remove(object key);
|
||||
public void Clear();
|
||||
public bool ContainsKey(object key);
|
||||
public object[] Serialize();
|
||||
}
|
||||
|
||||
public class Map<KT, VT> : IEnumerable<KeyValuePair<KT, VT>>, IMap
|
||||
{
|
||||
|
||||
//public struct StructureMetadata
|
||||
//{
|
||||
// public KT[] Keys;
|
||||
// public VT[] Types;
|
||||
//}
|
||||
|
||||
private Dictionary<KT, VT> dic = new Dictionary<KT, VT>();// StringComparer.OrdinalIgnoreCase);
|
||||
private object syncRoot = new object();
|
||||
|
||||
|
||||
public bool ContainsKey(KT key)
|
||||
{
|
||||
return dic.ContainsKey(key);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var rt = "";
|
||||
foreach (var kv in dic)
|
||||
rt += kv.Key + ": " + kv.Value.ToString() + " \r\n";
|
||||
|
||||
return rt.TrimEnd('\r', '\n');
|
||||
}
|
||||
|
||||
public Map(Map<KT,VT> source)
|
||||
{
|
||||
dic = source.dic;
|
||||
}
|
||||
public Map()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static Map<KT,VT> FromMap(Map<KT,VT> source, Type destinationType)
|
||||
{
|
||||
var rt = Activator.CreateInstance(destinationType) as Map<KT, VT>;
|
||||
rt.dic = source.dic;
|
||||
return rt;
|
||||
}
|
||||
|
||||
//public static T FromStructure<T>(Map<KT, VT> source) where T : Map<KT, VT>
|
||||
//{
|
||||
// var rt = Activator.CreateInstance<T>();
|
||||
// rt.dic = source.dic;
|
||||
// return rt;
|
||||
//}
|
||||
|
||||
// public static explicit operator Map<string, object>(ExpandoObject obj) => FromDynamic(obj);
|
||||
|
||||
public static Map<string, object> FromDynamic(ExpandoObject obj)
|
||||
{
|
||||
var rt = new Map<string, object>();
|
||||
foreach (var kv in obj)
|
||||
rt[kv.Key] = kv.Value;
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static Map<string,object> FromObject(object obj)
|
||||
{
|
||||
var type = obj.GetType();
|
||||
|
||||
var st = new Map<string,object>();
|
||||
|
||||
var pi = type.GetTypeInfo().GetProperties().Where(x => x.CanRead);
|
||||
foreach (var p in pi)
|
||||
st[p.Name] = p.GetValue(obj);
|
||||
|
||||
var fi = type.GetTypeInfo().GetFields().Where(x => x.IsPublic);
|
||||
foreach (var f in fi)
|
||||
st[f.Name] = f.GetValue(obj);
|
||||
|
||||
return st;
|
||||
|
||||
|
||||
// if (obj is Structure)
|
||||
// return obj as Structure;
|
||||
// else //if (Codec.IsAnonymous(type))
|
||||
// {
|
||||
// var st = new Structure();
|
||||
|
||||
// var pi = type.GetTypeInfo().GetProperties().Where(x => x.CanRead);
|
||||
// foreach (var p in pi)
|
||||
// st[p.Name] = p.GetValue(obj);
|
||||
|
||||
// var fi = type.GetTypeInfo().GetFields().Where(x => x.IsPublic);
|
||||
// foreach (var f in fi)
|
||||
// st[f.Name] = f.GetValue(obj);
|
||||
|
||||
// return st;
|
||||
// }
|
||||
// //else
|
||||
// // return null;
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<KT, VT>> GetEnumerator()
|
||||
{
|
||||
return dic.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return dic.GetEnumerator();
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get { return dic.Count; }
|
||||
}
|
||||
|
||||
public KeyValuePair<KT, VT> At(int index)
|
||||
{
|
||||
return dic.ElementAt(index);
|
||||
}
|
||||
|
||||
public object SyncRoot
|
||||
{
|
||||
get { return syncRoot; }
|
||||
}
|
||||
|
||||
public KT[] GetKeys() => dic.Keys.ToArray();//GetKeys()
|
||||
//{
|
||||
// return dic.Keys.ToArray();
|
||||
//}
|
||||
|
||||
public void Add(KT key, VT value)
|
||||
{
|
||||
if (dic.ContainsKey(key))
|
||||
dic[key] = value;
|
||||
else
|
||||
dic.Add(key, value);
|
||||
}
|
||||
|
||||
public void Add(object key, object value)
|
||||
{
|
||||
Add((KT)key, (VT)value);
|
||||
}
|
||||
|
||||
public void Remove(object key)
|
||||
{
|
||||
Remove((KT)key);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
dic.Clear();
|
||||
}
|
||||
|
||||
public bool ContainsKey(object key)
|
||||
{
|
||||
return ContainsKey((KT)key);
|
||||
}
|
||||
|
||||
public object[] Serialize()
|
||||
{
|
||||
var rt = new List<object>();
|
||||
foreach(var kv in dic)
|
||||
{
|
||||
rt.Add(kv.Key);
|
||||
rt.Add(kv.Value);
|
||||
}
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
public VT this[KT index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (dic.ContainsKey(index))
|
||||
return dic[index];
|
||||
else
|
||||
return default;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (dic.ContainsKey(index))
|
||||
dic[index] = value;
|
||||
else
|
||||
dic.Add(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -13,11 +13,11 @@ public class PropertyValue
|
||||
/// <summary>
|
||||
/// Get or set date of modification or occurrence.
|
||||
/// </summary>
|
||||
public DateTime Date { get; set; }
|
||||
public DateTime? Date { get; set; }
|
||||
/// <summary>
|
||||
/// Get or set property age.
|
||||
/// </summary>
|
||||
public ulong Age { get; set; }
|
||||
public ulong? Age { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of PropertyValue.
|
||||
@ -25,7 +25,7 @@ public class PropertyValue
|
||||
/// <param name="value">Value.</param>
|
||||
/// <param name="age">Age.</param>
|
||||
/// <param name="date">Date.</param>
|
||||
public PropertyValue(object value, ulong age, DateTime date)
|
||||
public PropertyValue(object value, ulong? age, DateTime? date)
|
||||
{
|
||||
Value = value;
|
||||
Age = age;
|
||||
|
@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Data;
|
||||
|
||||
public enum RecordComparisonResult : byte
|
||||
{
|
||||
Null,
|
||||
Record,
|
||||
RecordSameType,
|
||||
Same
|
||||
}
|
372
Esiur/Data/RepresentationType.cs
Normal file
372
Esiur/Data/RepresentationType.cs
Normal file
@ -0,0 +1,372 @@
|
||||
using Esiur.Net.IIP;
|
||||
using Esiur.Resource;
|
||||
using Esiur.Resource.Template;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Data
|
||||
{
|
||||
public enum RepresentationTypeIdentifier
|
||||
{
|
||||
Void,
|
||||
Dynamic,
|
||||
Bool,
|
||||
UInt8,
|
||||
Int8,
|
||||
Char,
|
||||
Int16,
|
||||
UInt16,
|
||||
Int32,
|
||||
UInt32,
|
||||
Float32,
|
||||
Int64,
|
||||
UInt64,
|
||||
Float64,
|
||||
DateTime,
|
||||
Int128,
|
||||
UInt128,
|
||||
Decimal,
|
||||
String,
|
||||
RawData,
|
||||
Resource,
|
||||
Record,
|
||||
List,
|
||||
Map,
|
||||
Enum = 0x44,
|
||||
TypedResource = 0x45, // Followed by UUID
|
||||
TypedRecord = 0x46, // Followed by UUID
|
||||
TypedList = 0x48, // Followed by element type
|
||||
Tuple2 = 0x50, // Followed by element type
|
||||
TypedMap = 0x51, // Followed by key type and value type
|
||||
Tuple3 = 0x58,
|
||||
Tuple4 = 0x60,
|
||||
Tuple5 = 0x68,
|
||||
Tuple6 = 0x70,
|
||||
Tuple7 = 0x78
|
||||
}
|
||||
|
||||
public class RepresentationType
|
||||
{
|
||||
public Type? GetRuntimeType()
|
||||
{
|
||||
return Identifier switch
|
||||
{
|
||||
(RepresentationTypeIdentifier.Void) => typeof(void),
|
||||
(RepresentationTypeIdentifier.Dynamic) => typeof(object),
|
||||
(RepresentationTypeIdentifier.Bool) => Nullable ? typeof(bool?) : typeof(bool),
|
||||
(RepresentationTypeIdentifier.Char) => Nullable ? typeof(char?) : typeof(char),
|
||||
(RepresentationTypeIdentifier.UInt8) => Nullable ? typeof(byte?) : typeof(byte),
|
||||
(RepresentationTypeIdentifier.Int8) => Nullable ? typeof(sbyte?) : typeof(sbyte),
|
||||
(RepresentationTypeIdentifier.Int16) => Nullable ? typeof(short?) : typeof(short),
|
||||
(RepresentationTypeIdentifier.UInt16) => Nullable ? typeof(ushort?) : typeof(ushort),
|
||||
(RepresentationTypeIdentifier.Int32) => Nullable ? typeof(int?) : typeof(int),
|
||||
(RepresentationTypeIdentifier.UInt32) => Nullable ? typeof(uint?) : typeof(uint),
|
||||
(RepresentationTypeIdentifier.Int64) => Nullable ? typeof(ulong?) : typeof(long),
|
||||
(RepresentationTypeIdentifier.UInt64) => Nullable ? typeof(ulong?) : typeof(ulong),
|
||||
(RepresentationTypeIdentifier.Float32) => Nullable ? typeof(float?) : typeof(float),
|
||||
(RepresentationTypeIdentifier.Float64) => Nullable ? typeof(double?) : typeof(double),
|
||||
(RepresentationTypeIdentifier.Decimal) => Nullable ? typeof(decimal?) : typeof(decimal),
|
||||
(RepresentationTypeIdentifier.String) => typeof(string), //Nullable ? typeof(Nullable<string>) : typeof(string),
|
||||
(RepresentationTypeIdentifier.DateTime) => Nullable ? typeof(DateTime?) : typeof(DateTime),
|
||||
(RepresentationTypeIdentifier.Resource) => typeof(IResource),
|
||||
(RepresentationTypeIdentifier.Record) => typeof(IRecord),
|
||||
(RepresentationTypeIdentifier.TypedRecord) => Warehouse.GetTemplateByClassId((Guid)GUID, TemplateType.Record).DefinedType,
|
||||
(RepresentationTypeIdentifier.TypedResource) => Warehouse.GetTemplateByClassId((Guid)GUID, TemplateType.Unspecified).DefinedType,
|
||||
(RepresentationTypeIdentifier.Enum) => Warehouse.GetTemplateByClassId((Guid)GUID, TemplateType.Enum).DefinedType,
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
public RepresentationTypeIdentifier Identifier;
|
||||
public bool Nullable;
|
||||
public Guid? GUID;
|
||||
//public RepresentationType? SubType1; // List + Map
|
||||
//public RepresentationType? SubType2; // Map
|
||||
//public RepresentationType? SubType3; // No types yet
|
||||
|
||||
public RepresentationType?[] SubTypes = new RepresentationType[3];
|
||||
|
||||
public static RepresentationType? FromType(Type type)
|
||||
{
|
||||
var nullType = System.Nullable.GetUnderlyingType(type);
|
||||
var nullable = false;
|
||||
|
||||
if (nullType != null) {
|
||||
type = nullType;
|
||||
nullable = true;
|
||||
}
|
||||
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
var genericType = type.GetGenericTypeDefinition();
|
||||
if (genericType == typeof(List<>))
|
||||
{
|
||||
var args = type.GetGenericArguments();
|
||||
if (args[0] == typeof(object))
|
||||
{
|
||||
return new RepresentationType(RepresentationTypeIdentifier.List, nullable);
|
||||
}
|
||||
else
|
||||
{
|
||||
var subType = FromType(args[0]);
|
||||
if (subType == null) // unrecongnized type
|
||||
return null;
|
||||
|
||||
return new RepresentationType(RepresentationTypeIdentifier.TypedList, nullable, null, subType);
|
||||
|
||||
}
|
||||
}
|
||||
else if (genericType == typeof(Map<,>))
|
||||
{
|
||||
var args = type.GetGenericArguments();
|
||||
if (args[0] == typeof(object) && args[1] == typeof(object))
|
||||
{
|
||||
return new RepresentationType(RepresentationTypeIdentifier.Map, nullable);
|
||||
}
|
||||
else
|
||||
{
|
||||
var subType1 = FromType(args[0]);
|
||||
if (subType1 == null)
|
||||
return null;
|
||||
|
||||
var subType2 = FromType(args[1]);
|
||||
if (subType2 == null)
|
||||
return null;
|
||||
|
||||
return new RepresentationType(RepresentationTypeIdentifier.TypedMap, nullable, null, subType1, subType2);
|
||||
}
|
||||
}
|
||||
else if (genericType == typeof(DistributedPropertyContext<>))
|
||||
{
|
||||
var args = type.GetGenericArguments();
|
||||
return FromType(args[0]);
|
||||
}
|
||||
else if (genericType == typeof(ValueTuple<,>))
|
||||
{
|
||||
var args = type.GetGenericArguments();
|
||||
var subTypes = new RepresentationType[args.Length];
|
||||
for (var i = 0; i < args.Length; i++)
|
||||
{
|
||||
subTypes[i] = FromType(args[i]);
|
||||
if (subTypes[i] == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple2, nullable, null, subTypes);
|
||||
}
|
||||
else if (genericType == typeof(ValueTuple<,,>))
|
||||
{
|
||||
var args = type.GetGenericArguments();
|
||||
var subTypes = new RepresentationType[args.Length];
|
||||
for(var i = 0; i < args.Length; i++)
|
||||
{
|
||||
subTypes[i] = FromType(args[i]);
|
||||
if (subTypes[i] == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple3, nullable, null, subTypes);
|
||||
}
|
||||
else if (genericType == typeof(ValueTuple<,,,>))
|
||||
{
|
||||
|
||||
var args = type.GetGenericArguments();
|
||||
var subTypes = new RepresentationType[args.Length];
|
||||
for (var i = 0; i < args.Length; i++)
|
||||
{
|
||||
subTypes[i] = FromType(args[i]);
|
||||
if (subTypes[i] == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple4, nullable, null, subTypes);
|
||||
}
|
||||
else if (genericType == typeof(ValueTuple<,,,,>))
|
||||
{
|
||||
var args = type.GetGenericArguments();
|
||||
var subTypes = new RepresentationType[args.Length];
|
||||
for (var i = 0; i < args.Length; i++)
|
||||
{
|
||||
subTypes[i] = FromType(args[i]);
|
||||
if (subTypes[i] == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple5, nullable, null, subTypes);
|
||||
}
|
||||
else if (genericType == typeof(ValueTuple<,,,,,>))
|
||||
{
|
||||
var args = type.GetGenericArguments();
|
||||
var subTypes = new RepresentationType[args.Length];
|
||||
for (var i = 0; i < args.Length; i++)
|
||||
{
|
||||
subTypes[i] = FromType(args[i]);
|
||||
if (subTypes[i] == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple6, nullable, null, subTypes);
|
||||
}
|
||||
else if (genericType == typeof(ValueTuple<,,,,,,>))
|
||||
{
|
||||
var args = type.GetGenericArguments();
|
||||
var subTypes = new RepresentationType[args.Length];
|
||||
for (var i = 0; i < args.Length; i++)
|
||||
{
|
||||
subTypes[i] = FromType(args[i]);
|
||||
if (subTypes[i] == null)
|
||||
return null;
|
||||
}
|
||||
|
||||
return new RepresentationType(RepresentationTypeIdentifier.Tuple7, nullable, null, subTypes);
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
else if (type.IsArray)
|
||||
{
|
||||
var elementType = type.GetElementType();
|
||||
if (elementType == typeof(object))
|
||||
return new RepresentationType(RepresentationTypeIdentifier.List, nullable);
|
||||
else
|
||||
{
|
||||
var subType = FromType(elementType);
|
||||
|
||||
if (subType == null)
|
||||
return null;
|
||||
|
||||
return new RepresentationType(RepresentationTypeIdentifier.TypedList, nullable, null, subType);
|
||||
|
||||
}
|
||||
}
|
||||
else if (type == typeof(IResource))
|
||||
return new RepresentationType(RepresentationTypeIdentifier.Resource, nullable);
|
||||
else if (type == typeof(IRecord) || type == typeof(Record))
|
||||
return new RepresentationType(RepresentationTypeIdentifier.Record, nullable);
|
||||
else if (type == typeof(Map<object, object>))
|
||||
return new RepresentationType(RepresentationTypeIdentifier.Map, nullable);
|
||||
else if (Codec.ImplementsInterface(type, typeof(IResource)))
|
||||
{
|
||||
return new RepresentationType(
|
||||
RepresentationTypeIdentifier.TypedResource,
|
||||
nullable,
|
||||
TypeTemplate.GetTypeGuid(type)
|
||||
);
|
||||
}
|
||||
else if (Codec.ImplementsInterface(type, typeof(IRecord)))
|
||||
{
|
||||
return new RepresentationType(
|
||||
RepresentationTypeIdentifier.TypedRecord,
|
||||
nullable,
|
||||
TypeTemplate.GetTypeGuid(type)
|
||||
);
|
||||
}
|
||||
else if (type.IsEnum)
|
||||
{
|
||||
return new RepresentationType(RepresentationTypeIdentifier.Enum, nullable, TypeTemplate.GetTypeGuid(type));
|
||||
}
|
||||
//else if (typeof(Structure).IsAssignableFrom(t) || t == typeof(ExpandoObject) => RepresentationTypeIdentifier.Structure)
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
return type switch
|
||||
{
|
||||
_ when type == typeof(void) => new RepresentationType(RepresentationTypeIdentifier.Void, nullable),
|
||||
_ when type == typeof(object) => new RepresentationType(RepresentationTypeIdentifier.Dynamic, nullable),
|
||||
_ when type == typeof(bool) => new RepresentationType(RepresentationTypeIdentifier.Bool, nullable),
|
||||
_ when type == typeof(char) => new RepresentationType(RepresentationTypeIdentifier.Char, nullable),
|
||||
_ when type == typeof(byte) => new RepresentationType(RepresentationTypeIdentifier.UInt8, nullable),
|
||||
_ when type == typeof(sbyte) => new RepresentationType(RepresentationTypeIdentifier.Int8, nullable),
|
||||
_ when type == typeof(short) => new RepresentationType(RepresentationTypeIdentifier.Int16, nullable),
|
||||
_ when type == typeof(ushort) => new RepresentationType(RepresentationTypeIdentifier.UInt16, nullable),
|
||||
_ when type == typeof(int) => new RepresentationType(RepresentationTypeIdentifier.Int32, nullable),
|
||||
_ when type == typeof(uint) => new RepresentationType(RepresentationTypeIdentifier.UInt32, nullable),
|
||||
_ when type == typeof(long) => new RepresentationType(RepresentationTypeIdentifier.Int64, nullable),
|
||||
_ when type == typeof(ulong) => new RepresentationType(RepresentationTypeIdentifier.UInt64, nullable),
|
||||
_ when type == typeof(float) => new RepresentationType(RepresentationTypeIdentifier.Float32, nullable),
|
||||
_ when type == typeof(double) => new RepresentationType(RepresentationTypeIdentifier.Float64, nullable),
|
||||
_ when type == typeof(decimal) => new RepresentationType(RepresentationTypeIdentifier.Decimal, nullable),
|
||||
_ when type == typeof(string) => new RepresentationType(RepresentationTypeIdentifier.String, nullable),
|
||||
_ when type == typeof(DateTime) => new RepresentationType(RepresentationTypeIdentifier.DateTime, nullable),
|
||||
_ => null
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public RepresentationType(RepresentationTypeIdentifier identifier, bool nullable, Guid? guid = null, params RepresentationType[] subTypes)
|
||||
{
|
||||
Nullable = nullable;
|
||||
Identifier = identifier;
|
||||
GUID = guid;
|
||||
SubTypes = subTypes;
|
||||
}
|
||||
|
||||
public byte[] Compose()
|
||||
{
|
||||
var rt = new BinaryList();
|
||||
|
||||
if (Nullable)
|
||||
rt.AddUInt8((byte)(0x80 | (byte)Identifier));
|
||||
else
|
||||
rt.AddUInt8((byte)Identifier);
|
||||
|
||||
if (GUID != null)
|
||||
rt.AddUInt8Array(DC.ToBytes((Guid)GUID));
|
||||
|
||||
if (SubTypes != null)
|
||||
for (var i = 0; i < SubTypes.Length; i++)
|
||||
rt.AddUInt8Array(SubTypes[i].Compose());
|
||||
|
||||
return rt.ToArray();
|
||||
}
|
||||
|
||||
|
||||
//public override string ToString() => Identifier.ToString() + (Nullable ? "?" : "")
|
||||
// + TypeTemplate != null ? "<" + TypeTemplate.ClassName + ">" : "";
|
||||
|
||||
|
||||
public static (uint, RepresentationType) Parse(byte[] data, uint offset)
|
||||
{
|
||||
var oOffset = offset;
|
||||
|
||||
var header = data[offset++];
|
||||
bool nullable = (header & 0x80) > 0;
|
||||
var identifier = (RepresentationTypeIdentifier)(header & 0x7F);
|
||||
|
||||
|
||||
if ((header & 0x40) > 0)
|
||||
{
|
||||
|
||||
var hasGUID = (header & 0x4) > 0;
|
||||
var subsCount = (header >> 3) & 0x7;
|
||||
|
||||
Guid? guid = null;
|
||||
|
||||
if (hasGUID)
|
||||
{
|
||||
guid = data.GetGuid(offset);
|
||||
offset += 16;
|
||||
}
|
||||
|
||||
var subs = new RepresentationType[subsCount];
|
||||
|
||||
for (var i = 0; i < subsCount; i++)
|
||||
{
|
||||
(var len, subs[i]) = RepresentationType.Parse(data, offset);
|
||||
offset += len;
|
||||
}
|
||||
|
||||
return (offset - oOffset, new RepresentationType(identifier, nullable, guid, subs));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (1, new RepresentationType(identifier, nullable));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Data;
|
||||
|
||||
public enum ResourceComparisonResult
|
||||
{
|
||||
Null, // null
|
||||
Distributed, // resource is distributed
|
||||
Local, // resource is local
|
||||
Same, // Same as previous
|
||||
}
|
@ -55,7 +55,7 @@ class ResourceJsonConverter : JsonConverter<IResource>
|
||||
foreach (var pt in resource.Instance.Template.Properties)
|
||||
{
|
||||
var rt = pt.PropertyInfo.GetValue(resource, null);
|
||||
if (rt is DistributedPropertyContext)
|
||||
if (rt != null && rt.GetType().IsGenericType)
|
||||
continue;
|
||||
|
||||
writer.WritePropertyName(options.PropertyNamingPolicy?.ConvertName(pt.Name) ?? pt.Name);
|
||||
|
@ -1,180 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2017 Ahmed Kh. Zamil
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Esiur.Data;
|
||||
using Esiur.Misc;
|
||||
using Esiur.Core;
|
||||
using System.Reflection;
|
||||
using System.Dynamic;
|
||||
|
||||
namespace Esiur.Data;
|
||||
|
||||
public class Structure : IEnumerable<KeyValuePair<string, object>>
|
||||
{
|
||||
|
||||
public struct StructureMetadata
|
||||
{
|
||||
public string[] Keys;
|
||||
public DataType[] Types;
|
||||
}
|
||||
|
||||
private Dictionary<string, object> dic = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
private object syncRoot = new object();
|
||||
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
return dic.ContainsKey(key);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var rt = "";
|
||||
foreach (var kv in dic)
|
||||
rt += kv.Key + ": " + kv.Value.ToString() + " \r\n";
|
||||
|
||||
return rt.TrimEnd('\r', '\n');
|
||||
}
|
||||
|
||||
public Structure(Structure source)
|
||||
{
|
||||
dic = source.dic;
|
||||
}
|
||||
public Structure()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static Structure FromStructure(Structure source, Type destinationType)
|
||||
{
|
||||
var rt = Activator.CreateInstance(destinationType) as Structure;
|
||||
rt.dic = source.dic;
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static T FromStructure<T>(Structure source) where T : Structure
|
||||
{
|
||||
var rt = Activator.CreateInstance<T>();
|
||||
rt.dic = source.dic;
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static explicit operator Structure(ExpandoObject obj) => FromDynamic(obj);
|
||||
|
||||
public static Structure FromDynamic(ExpandoObject obj)
|
||||
{
|
||||
var rt = new Structure();
|
||||
foreach (var kv in obj)
|
||||
rt[kv.Key] = kv.Value;
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static Structure FromObject(object obj)
|
||||
{
|
||||
var type = obj.GetType();
|
||||
|
||||
if (obj is Structure)
|
||||
return obj as Structure;
|
||||
else //if (Codec.IsAnonymous(type))
|
||||
{
|
||||
var st = new Structure();
|
||||
|
||||
var pi = type.GetTypeInfo().GetProperties().Where(x => x.CanRead);
|
||||
foreach (var p in pi)
|
||||
st[p.Name] = p.GetValue(obj);
|
||||
|
||||
var fi = type.GetTypeInfo().GetFields().Where(x => x.IsPublic);
|
||||
foreach (var f in fi)
|
||||
st[f.Name] = f.GetValue(obj);
|
||||
|
||||
return st;
|
||||
}
|
||||
//else
|
||||
// return null;
|
||||
}
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
return dic.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return dic.GetEnumerator();
|
||||
}
|
||||
|
||||
public int Length
|
||||
{
|
||||
get { return dic.Count; }
|
||||
}
|
||||
|
||||
public KeyValuePair<string, object> At(int index)
|
||||
{
|
||||
return dic.ElementAt(index);
|
||||
}
|
||||
|
||||
public object SyncRoot
|
||||
{
|
||||
get { return syncRoot; }
|
||||
}
|
||||
|
||||
public string[] GetKeys() => dic.Keys.ToArray();//GetKeys()
|
||||
//{
|
||||
// return dic.Keys.ToArray();
|
||||
//}
|
||||
|
||||
public Structure Add(string key, object value)
|
||||
{
|
||||
if (dic.ContainsKey(key))
|
||||
dic[key] = value;
|
||||
else
|
||||
dic.Add(key, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public object this[string index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (dic.ContainsKey(index))
|
||||
return dic[index];
|
||||
else
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (dic.ContainsKey(index))
|
||||
dic[index] = value;
|
||||
else
|
||||
dic.Add(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Data;
|
||||
|
||||
public enum StructureComparisonResult : byte
|
||||
{
|
||||
Null,
|
||||
Structure,
|
||||
StructureSameKeys,
|
||||
StructureSameTypes,
|
||||
Same
|
||||
}
|
247
Esiur/Data/TransmissionType.cs
Normal file
247
Esiur/Data/TransmissionType.cs
Normal file
@ -0,0 +1,247 @@
|
||||
using Esiur.Net.IIP;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Data;
|
||||
|
||||
public enum TransmissionTypeIdentifier : byte
|
||||
{
|
||||
Null = 0x0,
|
||||
False = 0x1,
|
||||
True = 0x2,
|
||||
NotModified = 0x3,
|
||||
UInt8 = 0x8,
|
||||
Int8 = 0x9,
|
||||
Char8 = 0xA,
|
||||
Int16 = 0x10,
|
||||
UInt16 = 0x11,
|
||||
Char16 = 0x12,
|
||||
Int32 = 0x18,
|
||||
UInt32 = 0x19,
|
||||
Float32 = 0x1A,
|
||||
Resource = 0x1B,
|
||||
ResourceLocal = 0x1C,
|
||||
Int64 = 0x20,
|
||||
UInt64 = 0x21,
|
||||
Float64 = 0x22,
|
||||
DateTime = 0x23,
|
||||
Int128 = 0x28,
|
||||
UInt128 = 0x29,
|
||||
Float128 = 0x2A,
|
||||
|
||||
RawData = 0x40,
|
||||
String = 0x41,
|
||||
List = 0x42,
|
||||
ResourceList = 0x43,
|
||||
RecordList = 0x44,
|
||||
Map = 0x45,
|
||||
MapList = 0x46,
|
||||
//Tuple = 0x47,
|
||||
|
||||
Record = 0x80,
|
||||
TypedList = 0x81,
|
||||
TypedMap = 0x82,
|
||||
Tuple = 0x83,
|
||||
Enum = 0x84,
|
||||
Constant = 0x85
|
||||
//TypedResourceList = 0x81,
|
||||
//TypedRecordList = 0x82,
|
||||
|
||||
}
|
||||
|
||||
public enum TransmissionTypeClass
|
||||
{
|
||||
Fixed = 0,
|
||||
Dynamic = 1,
|
||||
Typed = 2
|
||||
}
|
||||
|
||||
public struct TransmissionType
|
||||
{
|
||||
public TransmissionTypeIdentifier Identifier;
|
||||
public int Index;
|
||||
public TransmissionTypeClass Class;
|
||||
public uint Offset;
|
||||
public ulong ContentLength;
|
||||
public byte Exponent;
|
||||
|
||||
|
||||
public TransmissionType(TransmissionTypeIdentifier identifier, TransmissionTypeClass cls, int index, uint offset, ulong contentLength, byte exponent = 0)
|
||||
{
|
||||
Identifier = identifier;
|
||||
Index = index;
|
||||
Class = cls;
|
||||
Offset=offset;
|
||||
ContentLength = contentLength;
|
||||
Exponent = exponent;
|
||||
}
|
||||
|
||||
public static byte[] Compose(TransmissionTypeIdentifier identifier, byte[] data)
|
||||
{
|
||||
|
||||
if (data == null || data.Length == 0)
|
||||
return new byte[] { (byte)identifier };
|
||||
|
||||
var cls = (TransmissionTypeClass)((int)identifier >> 6);
|
||||
if (cls == TransmissionTypeClass.Fixed)
|
||||
{
|
||||
return DC.Combine(new byte[] { (byte)identifier }, 0, 1, data, 0, (uint)data.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
var len = (ulong)data.LongLength;
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
return new byte[1] { (byte) identifier };
|
||||
}
|
||||
else if (len <= 0xFF)
|
||||
{
|
||||
var rt = new byte[2 + len];
|
||||
rt[0] = (byte)((byte)identifier | 0x8);
|
||||
rt[1] = (byte)len;
|
||||
Buffer.BlockCopy(data, 0, rt, 2, (int)len);
|
||||
return rt;
|
||||
}
|
||||
else if (len <= 0xFF_FF)
|
||||
{
|
||||
var rt = new byte[3 + len];
|
||||
rt[0] = (byte)((byte)identifier | 0x10);
|
||||
rt[1] = (byte)((len >> 8) & 0xFF);
|
||||
rt[2] = (byte)(len & 0xFF);
|
||||
Buffer.BlockCopy(data, 0, rt, 3, (int)len);
|
||||
return rt;
|
||||
}
|
||||
else if (len <= 0xFF_FF_FF)
|
||||
{
|
||||
var rt = new byte[4 + len];
|
||||
rt[0] = (byte)((byte)identifier | 0x18);
|
||||
rt[1] = (byte)((len >> 16) & 0xFF);
|
||||
rt[2] = (byte)((len >> 8) & 0xFF);
|
||||
rt[3] = (byte)(len & 0xFF);
|
||||
Buffer.BlockCopy(data, 0, rt, 4, (int)len);
|
||||
return rt;
|
||||
}
|
||||
else if (len <= 0xFF_FF_FF_FF)
|
||||
{
|
||||
var rt = new byte[5 + len];
|
||||
rt[0] = (byte)((byte)identifier | 0x20);
|
||||
rt[1] = (byte)((len >> 24) & 0xFF);
|
||||
rt[2] = (byte)((len >> 16) & 0xFF);
|
||||
rt[3] = (byte)((len >> 8) & 0xFF);
|
||||
rt[4] = (byte)(len & 0xFF);
|
||||
Buffer.BlockCopy(data, 0, rt, 5, (int)len);
|
||||
return rt;
|
||||
}
|
||||
else if (len <= 0xFF_FF_FF_FF_FF)
|
||||
{
|
||||
var rt = new byte[6 + len];
|
||||
rt[0] = (byte)((byte)identifier | 0x28);
|
||||
rt[1] = (byte)((len >> 32) & 0xFF);
|
||||
rt[2] = (byte)((len >> 24) & 0xFF);
|
||||
rt[3] = (byte)((len >> 16) & 0xFF);
|
||||
rt[4] = (byte)((len >> 8) & 0xFF);
|
||||
rt[5] = (byte)(len & 0xFF);
|
||||
Buffer.BlockCopy(data, 0, rt, 6, (int)len);
|
||||
return rt;
|
||||
}
|
||||
else if (len <= 0xFF_FF_FF_FF_FF_FF)
|
||||
{
|
||||
var rt = new byte[7 + len];
|
||||
rt[0] = (byte)((byte)identifier | 0x30);
|
||||
rt[1] = (byte)((len >> 40) & 0xFF);
|
||||
rt[2] = (byte)((len >> 32) & 0xFF);
|
||||
rt[3] = (byte)((len >> 24) & 0xFF);
|
||||
rt[4] = (byte)((len >> 16) & 0xFF);
|
||||
rt[5] = (byte)((len >> 8) & 0xFF);
|
||||
rt[6] = (byte)(len & 0xFF);
|
||||
Buffer.BlockCopy(data, 0, rt, 7, (int)len);
|
||||
return rt;
|
||||
}
|
||||
else //if (len <= 0xFF_FF_FF_FF_FF_FF_FF)
|
||||
{
|
||||
var rt = new byte[8 + len];
|
||||
rt[0] = (byte)((byte)identifier | 0x38);
|
||||
rt[1] = (byte)((len >> 48) & 0xFF);
|
||||
rt[2] = (byte)((len >> 40) & 0xFF);
|
||||
rt[3] = (byte)((len >> 32) & 0xFF);
|
||||
rt[4] = (byte)((len >> 24) & 0xFF);
|
||||
rt[5] = (byte)((len >> 16) & 0xFF);
|
||||
rt[6] = (byte)((len >> 8) & 0xFF);
|
||||
rt[7] = (byte)(len & 0xFF);
|
||||
Buffer.BlockCopy(data, 0, rt, 8, (int)len);
|
||||
return rt;
|
||||
}
|
||||
//else // if (len <= 0xFF_FF_FF_FF_FF_FF_FF_FF)
|
||||
//{
|
||||
// var rt = new byte[9 + len];
|
||||
// rt[0] = (byte)((byte)identifier | 0x8);
|
||||
// rt[1] = (byte)((len >> 56) & 0xFF);
|
||||
// rt[2] = (byte)((len >> 48) & 0xFF);
|
||||
// rt[3] = (byte)((len >> 40) & 0xFF);
|
||||
// rt[4] = (byte)((len >> 32) & 0xFF);
|
||||
// rt[5] = (byte)((len >> 24) & 0xFF);
|
||||
// rt[6] = (byte)((len >> 16) & 0xFF);
|
||||
// rt[7] = (byte)((len >> 8) & 0xFF);
|
||||
// rt[8] = (byte)(len & 0xFF);
|
||||
// Buffer.BlockCopy(data, 0, rt, 9, (int)len);
|
||||
// return rt;
|
||||
//}
|
||||
|
||||
|
||||
// // add length
|
||||
// int bytes = 1;
|
||||
//for (var i = 56; i > 0; i -= 8, bytes++)
|
||||
// if (len <= (0xFF_FF_FF_FF_FF_FF_FF_FF >> i))
|
||||
// break;
|
||||
|
||||
//var rt = new byte[1 + bytes + data.Length];
|
||||
//rt[0] = (byte)((byte)identifier | (bytes << 3));
|
||||
|
||||
//for (var i = 1; i <= bytes; i++)
|
||||
// rt[i] = data.LongLength >> i * 8;
|
||||
|
||||
//Buffer.BlockCopy(data, 0, rt, 1 + bytes, data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public static (ulong, TransmissionType?) Parse(byte[] data, uint offset, uint ends)
|
||||
{
|
||||
var h = data[offset++];
|
||||
|
||||
var cls = (TransmissionTypeClass)(h >> 6);
|
||||
|
||||
if (cls == TransmissionTypeClass.Fixed)
|
||||
{
|
||||
var exp = (h & 0x38) >> 3;
|
||||
|
||||
if (exp == 0)
|
||||
return (1, new TransmissionType((TransmissionTypeIdentifier)h, cls, h & 0x7, 0, (byte)exp));
|
||||
|
||||
ulong cl = (ulong)(1 << (exp -1));
|
||||
|
||||
if (ends - offset < cl)
|
||||
return (ends - offset - (uint)cl, null);
|
||||
|
||||
//offset += (uint)cl;
|
||||
|
||||
return (1 + cl, new TransmissionType((TransmissionTypeIdentifier)h, cls, h & 0x7, offset, cl, (byte)exp));
|
||||
}
|
||||
else
|
||||
{
|
||||
ulong cll = (ulong)(h >> 3) & 0x7;
|
||||
|
||||
if (ends - offset < cll)
|
||||
return (ends - offset - (uint)cll, null);
|
||||
|
||||
ulong cl = 0;
|
||||
|
||||
for (uint i = 0; i < cll; i++)
|
||||
cl = cl << 8 | data[offset++];
|
||||
|
||||
return (1 + cl + cll, new TransmissionType((TransmissionTypeIdentifier)(h & 0xC7), cls, h & 0x7, offset, cl));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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>
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ public class PacketServer : IResource
|
||||
}
|
||||
|
||||
public event DestroyedEvent OnDestroy;
|
||||
public event PropertyModifiedEvent PropertyModified;
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -46,7 +46,6 @@ public abstract class HTTPFilter : IResource
|
||||
}
|
||||
|
||||
public event DestroyedEvent OnDestroy;
|
||||
|
||||
public abstract AsyncReply<bool> Trigger(ResourceTrigger trigger);
|
||||
|
||||
/*
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -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
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -66,7 +66,6 @@ public class TCPServer : NetworkServer<TCPConnection>, IResource
|
||||
|
||||
TCPFilter[] filters = null;
|
||||
|
||||
|
||||
public AsyncReply<bool> Trigger(ResourceTrigger trigger)
|
||||
{
|
||||
if (trigger == ResourceTrigger.Initialize)
|
||||
|
@ -35,6 +35,9 @@ using Esiur.Resource;
|
||||
namespace Esiur.Net.UDP;
|
||||
public abstract class UDPFilter : IResource
|
||||
{
|
||||
|
||||
|
||||
|
||||
public Instance Instance
|
||||
{
|
||||
get;
|
||||
|
@ -48,6 +48,7 @@ public class UDPServer : IResource
|
||||
|
||||
public event DestroyedEvent OnDestroy;
|
||||
|
||||
|
||||
public Instance Instance
|
||||
{
|
||||
get;
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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) {");
|
||||
|
||||
|
7
Esiur/Resource/CustomEventOccurredEvent.cs
Normal file
7
Esiur/Resource/CustomEventOccurredEvent.cs
Normal file
@ -0,0 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Resource;
|
||||
|
||||
public delegate void CustomEventOccurredEvent(CustomEventOccurredInfo info);
|
27
Esiur/Resource/CustomEventOccurredInfo.cs
Normal file
27
Esiur/Resource/CustomEventOccurredInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
8
Esiur/Resource/EventOccurredEvent.cs
Normal file
8
Esiur/Resource/EventOccurredEvent.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Resource
|
||||
{
|
||||
public delegate void EventOccurredEvent(EventOccurredInfo info);
|
||||
}
|
26
Esiur/Resource/EventOccurredInfo.cs
Normal file
26
Esiur/Resource/EventOccurredInfo.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -40,7 +40,6 @@ public delegate bool QueryFilter<T>(T value);
|
||||
|
||||
public interface IResource : IDestructible///, INotifyPropertyChanged
|
||||
{
|
||||
|
||||
AsyncReply<bool> Trigger(ResourceTrigger trigger);
|
||||
|
||||
[NotMapped]
|
||||
|
@ -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);
|
||||
|
@ -7,7 +7,7 @@ namespace Esiur.Resource;
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class ImportAttribute : Attribute
|
||||
{
|
||||
public ImportAttribute(string url)
|
||||
public ImportAttribute(params string[] urls)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
26
Esiur/Resource/PropertyModificationInfo.cs
Normal file
26
Esiur/Resource/PropertyModificationInfo.cs
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
7
Esiur/Resource/PropertyModifiedEvent.cs
Normal file
7
Esiur/Resource/PropertyModifiedEvent.cs
Normal file
@ -0,0 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Resource;
|
||||
|
||||
public delegate void PropertyModifiedEvent(PropertyModificationInfo data);
|
@ -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
|
||||
{
|
||||
|
@ -52,6 +52,7 @@ public class Resource : IResource
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
~Resource()
|
||||
{
|
||||
Destroy();
|
||||
|
8
Esiur/Resource/ResourceDestroyedEvent.cs
Normal file
8
Esiur/Resource/ResourceDestroyedEvent.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Resource
|
||||
{
|
||||
public delegate void ResourceDestroyedEvent(IResource resource);
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
67
Esiur/Resource/Template/ConstantTemplate.cs
Normal file
67
Esiur/Resource/Template/ConstantTemplate.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
Esiur/Resource/Template/CustomEventOccurredEvent.cs
Normal file
10
Esiur/Resource/Template/CustomEventOccurredEvent.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Esiur.Resource.Template
|
||||
{
|
||||
internal class CustomEventOccurredEvent
|
||||
{
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 });
|
||||
// }
|
||||
//}
|
||||
|
@ -9,4 +9,5 @@ public enum TemplateType : byte
|
||||
Resource,
|
||||
Record,
|
||||
Wrapper,
|
||||
Enum
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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; }
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
3
Esiur/TODO
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
1- Bin
|
||||
2- clean
|
21
Test.Client/Program.cs
Normal file
21
Test.Client/Program.cs
Normal 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);
|
||||
}
|
||||
|
||||
}
|
14
Test.Client/Test.Client.csproj
Normal file
14
Test.Client/Test.Client.csproj
Normal 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>
|
25
Test.Client/Test.Client.sln
Normal file
25
Test.Client/Test.Client.sln
Normal 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
|
8
Test.Client/localhost/Esiur.Generated.cs
Normal file
8
Test.Client/localhost/Esiur.Generated.cs
Normal 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) };
|
||||
}
|
||||
}
|
23
Test.Client/localhost/Test.MyChildResource.Generated.cs
Normal file
23
Test.Client/localhost/Test.MyChildResource.Generated.cs
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
16
Test.Client/localhost/Test.MyRecord.Generated.cs
Normal file
16
Test.Client/localhost/Test.MyRecord.Generated.cs
Normal 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; }
|
||||
|
||||
|
||||
}
|
||||
}
|
20
Test.Client/localhost/Test.MyResource.Generated.cs
Normal file
20
Test.Client/localhost/Test.MyResource.Generated.cs
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
257
Test.Client/localhost/Test.MyService.Generated.cs
Normal file
257
Test.Client/localhost/Test.MyService.Generated.cs
Normal 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;
|
||||
|
||||
|
||||
}
|
||||
}
|
15
Test.Client/localhost/Test.SizeEnum.Generated.cs
Normal file
15
Test.Client/localhost/Test.SizeEnum.Generated.cs
Normal 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
15
Test/MyChildRecord.cs
Normal 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
16
Test/MyChildResource.cs
Normal 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;
|
||||
}
|
||||
}
|
@ -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
Loading…
x
Reference in New Issue
Block a user