mirror of
https://github.com/esiur/esiur-dart.git
synced 2025-06-27 14:53:11 +00:00
1.3
This commit is contained in:
@ -22,25 +22,22 @@ SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
import 'package:esiur/src/Resource/Template/TemplateDescriber.dart';
|
||||
|
||||
import '../Resource/Template/TemplateDescriber.dart';
|
||||
import '../Core/IDestructible.dart';
|
||||
import 'ResourceTrigger.dart';
|
||||
import '../Core/AsyncReply.dart';
|
||||
import 'Instance.dart';
|
||||
|
||||
abstract class IResource extends IDestructible
|
||||
{
|
||||
abstract class IResource extends IDestructible {
|
||||
AsyncReply<bool> trigger(ResourceTrigger trigger);
|
||||
|
||||
AsyncReply<bool> trigger(ResourceTrigger trigger);
|
||||
/*
|
||||
{
|
||||
// do nothing
|
||||
return new AsyncReply.ready(true);
|
||||
}
|
||||
|
||||
destroy()
|
||||
{
|
||||
// Destroyed
|
||||
}
|
||||
*/
|
||||
Instance instance;
|
||||
}
|
||||
Instance instance;
|
||||
|
||||
invoke(String name, List arguments);
|
||||
setProperty(String name, value);
|
||||
getProperty(String name);
|
||||
|
||||
TemplateDescriber get template;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import '../Core/IEventHandler.dart';
|
||||
import '../Security/Permissions/Ruling.dart';
|
||||
import '../Security/Permissions/IPermissionsManager.dart';
|
||||
import '../Security/Permissions/ActionType.dart';
|
||||
import './Template/ResourceTemplate.dart';
|
||||
import 'Template/TypeTemplate.dart';
|
||||
import './Template/PropertyTemplate.dart';
|
||||
import './Template/FunctionTemplate.dart';
|
||||
import './Template/EventTemplate.dart';
|
||||
@ -30,7 +30,7 @@ class Instance extends IEventHandler
|
||||
IStore _store;
|
||||
AutoList<IResource, Instance> _parents;
|
||||
//bool inherit;
|
||||
ResourceTemplate _template;
|
||||
TypeTemplate _template;
|
||||
|
||||
AutoList<IPermissionsManager, Instance> _managers;
|
||||
|
||||
@ -547,7 +547,7 @@ class Instance extends IEventHandler
|
||||
/// <summary>
|
||||
/// Resource template describes the properties, functions and events of the resource.
|
||||
/// </summary>
|
||||
ResourceTemplate get template => _template;
|
||||
TypeTemplate get template => _template;
|
||||
|
||||
/// <summary>
|
||||
/// Check for permission.
|
||||
@ -583,7 +583,7 @@ class Instance extends IEventHandler
|
||||
/// <param name="name">Name of the instance.</param>
|
||||
/// <param name="resource">Resource to manage.</param>
|
||||
/// <param name="store">Store responsible for the resource.</param>
|
||||
Instance(int id, String name, IResource resource, IStore store, [ResourceTemplate customTemplate = null, int age = 0])
|
||||
Instance(int id, String name, IResource resource, IStore store, [TypeTemplate customTemplate = null, int age = 0])
|
||||
{
|
||||
_store = store;
|
||||
_resource = resource;
|
||||
|
34
lib/src/Resource/Template/ArgumentTemplate.dart
Normal file
34
lib/src/Resource/Template/ArgumentTemplate.dart
Normal file
@ -0,0 +1,34 @@
|
||||
import '../../Data/DC.dart';
|
||||
import '../../Data/BinaryList.dart';
|
||||
import "../../Data/ParseResult.dart";
|
||||
import './TemplateDataType.dart';
|
||||
|
||||
class ArgumentTemplate
|
||||
{
|
||||
String name;
|
||||
|
||||
TemplateDataType type;
|
||||
|
||||
static ParseResult<ArgumentTemplate> parse(DC data, int offset)
|
||||
{
|
||||
var cs = data[offset++];
|
||||
var name = data.getString(offset, cs);
|
||||
offset += cs;
|
||||
var tdr = TemplateDataType.parse(data, offset);
|
||||
|
||||
return ParseResult<ArgumentTemplate>(cs + 1 + tdr.size, ArgumentTemplate(name, tdr.value));
|
||||
}
|
||||
|
||||
ArgumentTemplate(this.name, this.type);
|
||||
|
||||
DC compose()
|
||||
{
|
||||
var name = DC.stringToBytes(this.name);
|
||||
|
||||
return new BinaryList()
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addDC(type.compose())
|
||||
.toDC();
|
||||
}
|
||||
}
|
@ -1,45 +1,39 @@
|
||||
|
||||
import 'MemberTemplate.dart';
|
||||
import '../../Data/DC.dart';
|
||||
import '../../Data/BinaryList.dart';
|
||||
import 'ResourceTemplate.dart';
|
||||
import 'TypeTemplate.dart';
|
||||
import 'MemberType.dart';
|
||||
import 'TemplateDataType.dart';
|
||||
|
||||
class EventTemplate extends MemberTemplate
|
||||
{
|
||||
|
||||
class EventTemplate extends MemberTemplate {
|
||||
String expansion;
|
||||
bool listenable;
|
||||
TemplateDataType argumentType;
|
||||
|
||||
DC compose() {
|
||||
var name = super.compose();
|
||||
|
||||
DC compose()
|
||||
{
|
||||
var name = super.compose();
|
||||
|
||||
if (expansion != null)
|
||||
{
|
||||
var exp = DC.stringToBytes(expansion);
|
||||
return new BinaryList()
|
||||
.addUint8(0x50)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addInt32(exp.length)
|
||||
.addDC(exp)
|
||||
.toDC();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new BinaryList()
|
||||
.addUint8(0x40)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.toDC();
|
||||
}
|
||||
if (expansion != null) {
|
||||
var exp = DC.stringToBytes(expansion);
|
||||
return new BinaryList()
|
||||
.addUint8(listenable ? 0x58 : 0x50)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addDC(argumentType.compose())
|
||||
.addInt32(exp.length)
|
||||
.addDC(exp)
|
||||
.toDC();
|
||||
} else {
|
||||
return new BinaryList()
|
||||
.addUint8(listenable ? 0x48 : 0x40)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addDC(argumentType.compose())
|
||||
.toDC();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EventTemplate(ResourceTemplate template, int index, String name, String expansion)
|
||||
: super(template, MemberType.Property, index, name)
|
||||
{
|
||||
this.expansion = expansion;
|
||||
}
|
||||
EventTemplate(TypeTemplate template, int index, String name,
|
||||
this.argumentType, this.expansion, this.listenable)
|
||||
: super(template, MemberType.Property, index, name) {}
|
||||
}
|
||||
|
@ -1,42 +1,49 @@
|
||||
import 'MemberTemplate.dart';
|
||||
import '../../Data/DC.dart';
|
||||
import '../../Data/BinaryList.dart';
|
||||
import 'ResourceTemplate.dart';
|
||||
import 'TypeTemplate.dart';
|
||||
import 'MemberType.dart';
|
||||
import 'ArgumentTemplate.dart';
|
||||
import 'TemplateDataType.dart';
|
||||
|
||||
class FunctionTemplate extends MemberTemplate
|
||||
{
|
||||
class FunctionTemplate extends MemberTemplate {
|
||||
String expansion;
|
||||
bool isVoid;
|
||||
|
||||
String expansion;
|
||||
bool isVoid;
|
||||
|
||||
TemplateDataType returnType;
|
||||
List<ArgumentTemplate> arguments;
|
||||
|
||||
DC compose()
|
||||
{
|
||||
var name = super.compose();
|
||||
DC compose() {
|
||||
|
||||
if (expansion != null)
|
||||
{
|
||||
var exp = DC.stringToBytes(expansion);
|
||||
return new BinaryList().addUint8((0x10 | (isVoid ? 0x8 : 0x0)))
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addInt32(exp.length)
|
||||
.addDC(exp)
|
||||
.toDC();
|
||||
}
|
||||
else
|
||||
return new BinaryList().addUint8((isVoid ? 0x8 : 0x0))
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.toDC();
|
||||
}
|
||||
var name = super.compose();
|
||||
|
||||
var bl = new BinaryList()
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addDC(returnType.compose())
|
||||
.addUint8(arguments.length);
|
||||
|
||||
for (var i = 0; i < arguments.length; i++)
|
||||
bl.addDC(arguments[i].compose());
|
||||
|
||||
|
||||
FunctionTemplate(ResourceTemplate template, int index, String name, bool isVoid, String expansion)
|
||||
:super(template, MemberType.Property, index, name)
|
||||
{
|
||||
this.isVoid = isVoid;
|
||||
this.expansion = expansion;
|
||||
}
|
||||
if (expansion != null)
|
||||
{
|
||||
var exp = DC.stringToBytes(expansion);
|
||||
bl.addInt32(exp.length)
|
||||
.addDC(exp);
|
||||
bl.insertUint8(0, 0x10);
|
||||
}
|
||||
else
|
||||
bl.insertUint8(0, 0x0);
|
||||
|
||||
return bl.toDC();
|
||||
}
|
||||
|
||||
FunctionTemplate(TypeTemplate template, int index, String name,
|
||||
this.arguments, this.returnType, String expansion)
|
||||
: super(template, MemberType.Property, index, name) {
|
||||
this.isVoid = isVoid;
|
||||
this.expansion = expansion;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
import 'MemberType.dart';
|
||||
import '../../Data/DC.dart';
|
||||
import './ResourceTemplate.dart';
|
||||
import 'TypeTemplate.dart';
|
||||
|
||||
class MemberTemplate
|
||||
{
|
||||
@ -10,14 +10,14 @@ class MemberTemplate
|
||||
String get name => _name;
|
||||
MemberType get type => _type;
|
||||
|
||||
ResourceTemplate _template;
|
||||
TypeTemplate _template;
|
||||
String _name;
|
||||
MemberType _type;
|
||||
int _index;
|
||||
|
||||
ResourceTemplate get template => _template;
|
||||
TypeTemplate get template => _template;
|
||||
|
||||
MemberTemplate(ResourceTemplate template, MemberType type, int index, String name)
|
||||
MemberTemplate(TypeTemplate template, MemberType type, int index, String name)
|
||||
{
|
||||
this._template = template;
|
||||
this._type = type;
|
||||
|
@ -1,80 +1,76 @@
|
||||
import 'TemplateDataType.dart';
|
||||
|
||||
import 'MemberTemplate.dart';
|
||||
import '../../Data/DC.dart';
|
||||
import '../../Data/BinaryList.dart';
|
||||
import 'ResourceTemplate.dart';
|
||||
import 'TypeTemplate.dart';
|
||||
import 'MemberType.dart';
|
||||
import 'PropertyPermission.dart';
|
||||
import '../StorageMode.dart';
|
||||
|
||||
class PropertyTemplate extends MemberTemplate
|
||||
{
|
||||
|
||||
class PropertyTemplate extends MemberTemplate {
|
||||
TemplateDataType valueType;
|
||||
|
||||
int permission;
|
||||
int permission;
|
||||
|
||||
int storage;
|
||||
|
||||
int storage;
|
||||
String readExpansion;
|
||||
|
||||
String readExpansion;
|
||||
String writeExpansion;
|
||||
|
||||
String writeExpansion;
|
||||
DC compose() {
|
||||
var name = super.compose();
|
||||
var pv = ((permission) << 1) | (storage == StorageMode.Recordable ? 1 : 0);
|
||||
|
||||
DC compose()
|
||||
{
|
||||
var name = super.compose();
|
||||
var pv = ((permission) << 1) | (storage == StorageMode.Recordable ? 1 : 0);
|
||||
if (writeExpansion != null && readExpansion != null) {
|
||||
var rexp = DC.stringToBytes(readExpansion);
|
||||
var wexp = DC.stringToBytes(writeExpansion);
|
||||
return new BinaryList()
|
||||
.addUint8(0x38 | pv)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addDC(valueType.compose())
|
||||
.addInt32(wexp.length)
|
||||
.addDC(wexp)
|
||||
.addInt32(rexp.length)
|
||||
.addDC(rexp)
|
||||
.toDC();
|
||||
} else if (writeExpansion != null) {
|
||||
var wexp = DC.stringToBytes(writeExpansion);
|
||||
return new BinaryList()
|
||||
.addUint8(0x30 | pv)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addDC(valueType.compose())
|
||||
.addInt32(wexp.length)
|
||||
.addDC(wexp)
|
||||
.toDC();
|
||||
} else if (readExpansion != null) {
|
||||
var rexp = DC.stringToBytes(readExpansion);
|
||||
return new BinaryList()
|
||||
.addUint8(0x28 | pv)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addDC(valueType.compose())
|
||||
.addInt32(rexp.length)
|
||||
.addDC(rexp)
|
||||
.toDC();
|
||||
} else
|
||||
return new BinaryList()
|
||||
.addUint8(0x20 | pv)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addDC(valueType.compose())
|
||||
.toDC();
|
||||
}
|
||||
|
||||
if (writeExpansion != null && readExpansion != null)
|
||||
{
|
||||
var rexp = DC.stringToBytes(readExpansion);
|
||||
var wexp = DC.stringToBytes(writeExpansion);
|
||||
return new BinaryList()
|
||||
.addUint8(0x38 | pv)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addInt32(wexp.length)
|
||||
.addDC(wexp)
|
||||
.addInt32(rexp.length)
|
||||
.addDC(rexp)
|
||||
.toDC();
|
||||
}
|
||||
else if (writeExpansion != null)
|
||||
{
|
||||
var wexp = DC.stringToBytes(writeExpansion);
|
||||
return new BinaryList()
|
||||
.addUint8(0x30 | pv)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addInt32(wexp.length)
|
||||
.addDC(wexp)
|
||||
.toDC();
|
||||
}
|
||||
else if (readExpansion != null)
|
||||
{
|
||||
var rexp = DC.stringToBytes(readExpansion);
|
||||
return new BinaryList()
|
||||
.addUint8(0x28 | pv)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.addInt32(rexp.length)
|
||||
.addDC(rexp)
|
||||
.toDC();
|
||||
}
|
||||
else
|
||||
return new BinaryList()
|
||||
.addUint8(0x20 | pv)
|
||||
.addUint8(name.length)
|
||||
.addDC(name)
|
||||
.toDC();
|
||||
}
|
||||
|
||||
PropertyTemplate(ResourceTemplate template, int index, String name, String read, String write, int storage)
|
||||
:super(template, MemberType.Property, index, name)
|
||||
{
|
||||
//this.Recordable = recordable;
|
||||
this.storage = storage;
|
||||
this.readExpansion = read;
|
||||
this.writeExpansion = write;
|
||||
}
|
||||
}
|
||||
PropertyTemplate(TypeTemplate template, int index, String name,
|
||||
TemplateDataType valueType, String read, String write, int storage)
|
||||
: super(template, MemberType.Property, index, name) {
|
||||
//this.Recordable = recordable;
|
||||
this.storage = storage;
|
||||
this.readExpansion = read;
|
||||
this.writeExpansion = write;
|
||||
this.valueType = valueType;
|
||||
}
|
||||
}
|
||||
|
@ -1,330 +0,0 @@
|
||||
|
||||
import './MemberTemplate.dart';
|
||||
import '../../Data/Guid.dart';
|
||||
import '../../Data/DC.dart';
|
||||
import './EventTemplate.dart';
|
||||
import './PropertyTemplate.dart';
|
||||
import './FunctionTemplate.dart';
|
||||
import '../StorageMode.dart';
|
||||
|
||||
class ResourceTemplate
|
||||
{
|
||||
Guid _classId;
|
||||
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>();
|
||||
int _version;
|
||||
//bool isReady;
|
||||
|
||||
DC _content;
|
||||
|
||||
DC get content => _content;
|
||||
|
||||
/*
|
||||
MemberTemplate getMemberTemplate(MemberInfo member)
|
||||
{
|
||||
if (member is MethodInfo)
|
||||
return getFunctionTemplate(member.Name);
|
||||
else if (member is EventInfo)
|
||||
return getEventTemplate(member.Name);
|
||||
else if (member is PropertyInfo)
|
||||
return getPropertyTemplate(member.Name);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
EventTemplate getEventTemplateByName(String eventName)
|
||||
{
|
||||
for (var i in _events)
|
||||
if (i.name == eventName)
|
||||
return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
EventTemplate getEventTemplateByIndex(int index)
|
||||
{
|
||||
for (var i in _events)
|
||||
if (i.index == index)
|
||||
return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
FunctionTemplate getFunctionTemplateByName(String functionName)
|
||||
{
|
||||
for (var i in _functions)
|
||||
if (i.name == functionName)
|
||||
return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
FunctionTemplate getFunctionTemplateByIndex(int index)
|
||||
{
|
||||
for (var i in _functions)
|
||||
if (i.index == index)
|
||||
return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyTemplate getPropertyTemplateByIndex(int index)
|
||||
{
|
||||
for (var i in _properties)
|
||||
if (i.index == index)
|
||||
return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyTemplate getPropertyTemplateByName(String propertyName)
|
||||
{
|
||||
for (var i in _properties)
|
||||
if (i.name == propertyName)
|
||||
return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
Guid get classId => _classId;
|
||||
|
||||
String get className => _className;
|
||||
|
||||
List<MemberTemplate> get methods => _members;
|
||||
|
||||
List<FunctionTemplate> get functions => _functions;
|
||||
|
||||
List<EventTemplate> get events => _events;
|
||||
|
||||
List<PropertyTemplate> get properties => _properties;
|
||||
|
||||
ResourceTemplate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
ResourceTemplate.fromType(Type type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
ResourceTemplate(Type type)
|
||||
{
|
||||
|
||||
type = ResourceProxy.GetBaseType(type);
|
||||
|
||||
// set guid
|
||||
|
||||
var typeName = Encoding.UTF8.GetBytes(type.FullName);
|
||||
var hash = SHA256.Create().ComputeHash(typeName).Clip(0, 16);
|
||||
|
||||
classId = new Guid(hash);
|
||||
className = type.FullName;
|
||||
|
||||
|
||||
#if NETSTANDARD1_5
|
||||
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
|
||||
|
||||
//byte currentIndex = 0;
|
||||
|
||||
byte i = 0;
|
||||
|
||||
foreach (var pi in propsInfo)
|
||||
{
|
||||
var ps = (ResourceProperty[])pi.GetCustomAttributes(typeof(ResourceProperty), true);
|
||||
if (ps.Length > 0)
|
||||
{
|
||||
var pt = new PropertyTemplate(this, i++, pi.Name, ps[0].ReadExpansion, ps[0].WriteExpansion, ps[0].Storage);
|
||||
pt.Info = pi;
|
||||
properties.Add(pt);
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
foreach (var ei in eventsInfo)
|
||||
{
|
||||
var es = (ResourceEvent[])ei.GetCustomAttributes(typeof(ResourceEvent), true);
|
||||
if (es.Length > 0)
|
||||
{
|
||||
var et = new EventTemplate(this, i++, ei.Name, es[0].Expansion);
|
||||
events.Add(et);
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
foreach (MethodInfo mi in methodsInfo)
|
||||
{
|
||||
var fs = (ResourceFunction[])mi.GetCustomAttributes(typeof(ResourceFunction), true);
|
||||
if (fs.Length > 0)
|
||||
{
|
||||
var ft = new FunctionTemplate(this, i++, mi.Name, mi.ReturnType == typeof(void), fs[0].Expansion);
|
||||
functions.Add(ft);
|
||||
}
|
||||
}
|
||||
|
||||
// append signals
|
||||
for (i = 0; i < events.Count; i++)
|
||||
members.Add(events[i]);
|
||||
// append slots
|
||||
for (i = 0; i < functions.Count; i++)
|
||||
members.Add(functions[i]);
|
||||
// append properties
|
||||
for (i = 0; i < properties.Count; i++)
|
||||
members.Add(properties[i]);
|
||||
|
||||
// bake it binarily
|
||||
var b = new BinaryList();
|
||||
b.AddGuid(classId)
|
||||
.AddUInt8((byte)className.Length)
|
||||
.AddString(className)
|
||||
.AddInt32(version)
|
||||
.AddUInt16((ushort)members.Count);
|
||||
|
||||
|
||||
foreach (var ft in functions)
|
||||
b.AddUInt8Array(ft.Compose());
|
||||
foreach (var pt in properties)
|
||||
b.AddUInt8Array(pt.Compose());
|
||||
foreach (var et in events)
|
||||
b.AddUInt8Array(et.Compose());
|
||||
|
||||
content = b.ToArray();
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
ResourceTemplate.parse(DC data, [int offset = 0, int contentLength])
|
||||
{
|
||||
|
||||
// cool Dart feature
|
||||
contentLength ??= data.length;
|
||||
|
||||
|
||||
int ends = offset + contentLength;
|
||||
|
||||
int oOffset = offset;
|
||||
|
||||
// start parsing...
|
||||
|
||||
//var od = new ResourceTemplate();
|
||||
_content = data.clip(offset, contentLength);
|
||||
|
||||
_classId = data.getGuid(offset);
|
||||
offset += 16;
|
||||
_className = data.getString(offset + 1, data[offset]);
|
||||
offset += data[offset] + 1;
|
||||
|
||||
_version = data.getInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
var methodsCount = data.getUint16(offset);
|
||||
offset += 2;
|
||||
|
||||
var functionIndex = 0;
|
||||
var propertyIndex = 0;
|
||||
var eventIndex = 0;
|
||||
|
||||
for (int i = 0; i < methodsCount; i++)
|
||||
{
|
||||
var type = data[offset] >> 5;
|
||||
|
||||
if (type == 0) // function
|
||||
{
|
||||
String expansion = null;
|
||||
var hasExpansion = ((data[offset] & 0x10) == 0x10);
|
||||
var isVoid = ((data[offset++] & 0x08) == 0x08);
|
||||
var name = data.getString(offset + 1, data[offset]);
|
||||
offset += data[offset] + 1;
|
||||
|
||||
if (hasExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.getUint32(offset);
|
||||
offset += 4;
|
||||
expansion = data.getString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var ft = new FunctionTemplate(this, functionIndex++, name, isVoid, expansion);
|
||||
|
||||
_functions.add(ft);
|
||||
}
|
||||
else if (type == 1) // property
|
||||
{
|
||||
|
||||
String readExpansion = null, writeExpansion = null;
|
||||
|
||||
var hasReadExpansion = ((data[offset] & 0x8) == 0x8);
|
||||
var hasWriteExpansion = ((data[offset] & 0x10) == 0x10);
|
||||
var recordable = ((data[offset] & 1) == 1);
|
||||
var permission = (data[offset++] >> 1) & 0x3;
|
||||
var name = data.getString(offset + 1, data[offset]);
|
||||
|
||||
offset += data[offset] + 1;
|
||||
|
||||
if (hasReadExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.getUint32(offset);
|
||||
offset += 4;
|
||||
readExpansion = data.getString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
if (hasWriteExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.getUint32(offset);
|
||||
offset += 4;
|
||||
writeExpansion = data.getString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var pt = new PropertyTemplate(this, propertyIndex++, name, readExpansion, writeExpansion, recordable ? StorageMode.Recordable : StorageMode.Volatile);
|
||||
|
||||
_properties.add(pt);
|
||||
}
|
||||
else if (type == 2) // Event
|
||||
{
|
||||
|
||||
String expansion = null;
|
||||
var hasExpansion = ((data[offset++] & 0x10) == 0x10);
|
||||
|
||||
var name = data.getString(offset + 1, data[offset]);// Encoding.ASCII.GetString(data, (int)offset + 1, (int)data[offset]);
|
||||
offset += data[offset] + 1;
|
||||
|
||||
if (hasExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.getUint32(offset);
|
||||
offset += 4;
|
||||
expansion = data.getString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var et = new EventTemplate(this, eventIndex++, name, expansion);
|
||||
|
||||
_events.add(et);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// append signals
|
||||
for (int i = 0; i < _events.length; i++)
|
||||
_members.add(_events[i]);
|
||||
// append slots
|
||||
for (int i = 0; i < _functions.length; i++)
|
||||
_members.add(_functions[i]);
|
||||
// append properties
|
||||
for (int i = 0; i < _properties.length; i++)
|
||||
_members.add(_properties[i]);
|
||||
|
||||
}
|
||||
}
|
||||
|
120
lib/src/Resource/Template/TemplateDataType.dart
Normal file
120
lib/src/Resource/Template/TemplateDataType.dart
Normal file
@ -0,0 +1,120 @@
|
||||
import 'dart:ffi';
|
||||
|
||||
import '../../Data/IRecord.dart';
|
||||
import '../../Resource/IResource.dart';
|
||||
|
||||
import '../../Data/Structure.dart';
|
||||
|
||||
import '../../Data/ParseResult.dart';
|
||||
|
||||
import '../../Data/DataType.dart';
|
||||
import '../../Data/Guid.dart';
|
||||
import '../../Data/DC.dart';
|
||||
import '../../Data/BinaryList.dart';
|
||||
import 'TypeTemplate.dart';
|
||||
import '../../Resource/Warehouse.dart';
|
||||
import 'TemplateType.dart';
|
||||
|
||||
class TemplateDataType {
|
||||
int type;
|
||||
TypeTemplate get typeTemplate =>
|
||||
typeGuid == null ? null : Warehouse.getTemplateByClassId(typeGuid);
|
||||
|
||||
Guid typeGuid;
|
||||
|
||||
// @TODO: implement fromType
|
||||
TemplateDataType.fromType(type, bool isArray) {
|
||||
int dt;
|
||||
|
||||
if (type == null)
|
||||
dt = DataType.Void;
|
||||
else if (type is int) {
|
||||
dt = type;
|
||||
} else if (type == bool)
|
||||
dt = DataType.Bool;
|
||||
else if (type == Uint8)
|
||||
dt = DataType.UInt8;
|
||||
else if (type == Int8)
|
||||
dt = DataType.Int8;
|
||||
else if (type == Uint16)
|
||||
dt = DataType.UInt16;
|
||||
else if (type == Int16)
|
||||
dt = DataType.Int16;
|
||||
else if (type == Uint32)
|
||||
dt = DataType.UInt32;
|
||||
else if (type == Int32)
|
||||
dt = DataType.Int32;
|
||||
else if (type == Uint64)
|
||||
dt = DataType.UInt64;
|
||||
else if (type == Int64 || type == int)
|
||||
dt = DataType.Int64;
|
||||
else if (type == Float)
|
||||
dt = DataType.Float32;
|
||||
else if (type == Double)
|
||||
dt = DataType.Float64;
|
||||
else if (type == String)
|
||||
dt = DataType.String;
|
||||
else if (type == DateTime)
|
||||
dt = DataType.DateTime;
|
||||
else if (type == Structure)
|
||||
dt = DataType.Structure;
|
||||
else if (type == IResource) // Dynamic resource (unspecified type)
|
||||
dt = DataType.Void;
|
||||
else if (type == IRecord) // Dynamic record (unspecified type)
|
||||
dt = DataType.Void;
|
||||
else {
|
||||
var template = Warehouse.getTemplateByType(type);
|
||||
|
||||
if (template != null) {
|
||||
typeGuid = template.classId;
|
||||
dt = template.type == TemplateType.Resource
|
||||
? DataType.Resource
|
||||
: DataType.Record;
|
||||
} else
|
||||
dt = DataType.Void;
|
||||
|
||||
// if (template)
|
||||
// try {
|
||||
// var ins = Warehouse.createInstance(type);
|
||||
// if (ins is IResource) {
|
||||
// typeGuid = TypeTemplate.getTypeGuid(ins.template.nameSpace);
|
||||
// } else if (ins is IRecord) {
|
||||
// typeGuid = TypeTemplate.getTypeGuid(ins.template.nameSpace);
|
||||
// } else {
|
||||
// dt = DataType.Void;
|
||||
// }
|
||||
// } catch (ex) {
|
||||
// dt = DataType.Void;
|
||||
// }
|
||||
}
|
||||
|
||||
if (isArray) dt = dt | 0x80;
|
||||
|
||||
this.type = dt;
|
||||
}
|
||||
|
||||
DC compose() {
|
||||
if (type == DataType.Resource ||
|
||||
type == DataType.ResourceArray ||
|
||||
type == DataType.Record ||
|
||||
type == DataType.RecordArray) {
|
||||
return BinaryList().addUint8(type).addDC(typeGuid.value).toDC();
|
||||
} else
|
||||
return DC.fromList([type]);
|
||||
}
|
||||
|
||||
TemplateDataType(this.type, this.typeGuid);
|
||||
|
||||
static ParseResult<TemplateDataType> parse(DC data, int offset) {
|
||||
var type = data[offset++];
|
||||
if (type == DataType.Resource ||
|
||||
type == DataType.ResourceArray ||
|
||||
type == DataType.Record ||
|
||||
type == DataType.RecordArray) {
|
||||
var guid = data.getGuid(offset);
|
||||
return ParseResult<TemplateDataType>(
|
||||
17, new TemplateDataType(type, guid));
|
||||
} else
|
||||
return ParseResult<TemplateDataType>(1, new TemplateDataType(type, null));
|
||||
}
|
||||
}
|
81
lib/src/Resource/Template/TemplateDescriber.dart
Normal file
81
lib/src/Resource/Template/TemplateDescriber.dart
Normal file
@ -0,0 +1,81 @@
|
||||
import '../../Data/DataType.dart';
|
||||
|
||||
class TemplateDescriber {
|
||||
final List<Prop> properties;
|
||||
final List<Evt> events;
|
||||
final List<Func> functions;
|
||||
final String nameSpace;
|
||||
|
||||
TemplateDescriber(this.nameSpace,
|
||||
{this.properties, this.functions, this.events});
|
||||
}
|
||||
|
||||
// class Property<T> {
|
||||
// T _value;
|
||||
|
||||
// Function(T) _setter;
|
||||
// Function() _getter;
|
||||
// Function(Property) notifier;
|
||||
|
||||
// IResource resource;
|
||||
|
||||
// operator <<(other) {
|
||||
// set(other);
|
||||
// }
|
||||
|
||||
// void set(T value) {
|
||||
// if (_setter != null)
|
||||
// _setter(value);
|
||||
// else
|
||||
// _value = value;
|
||||
|
||||
// if (notifier != null) notifier.call(this);
|
||||
// }
|
||||
|
||||
// T get() {
|
||||
// if (_getter != null)
|
||||
// return _getter();
|
||||
// else
|
||||
// return _value;
|
||||
// }
|
||||
|
||||
// Property([Function() getter, Function(T) setter]) {}
|
||||
// }
|
||||
|
||||
class Prop {
|
||||
final String name;
|
||||
final Type type;
|
||||
final bool isArray;
|
||||
final String readAnnotation;
|
||||
final String writeAnnotation;
|
||||
Prop(this.name, this.type, this.isArray, [this.readAnnotation = null, this.writeAnnotation = null]);
|
||||
}
|
||||
|
||||
class Evt {
|
||||
final String name;
|
||||
final bool listenable;
|
||||
final Type type;
|
||||
final bool isArray;
|
||||
final String annotation;
|
||||
|
||||
Evt(this.name, this.type, this.isArray, [this.listenable = false, this.annotation]);
|
||||
}
|
||||
|
||||
class Func {
|
||||
final String name;
|
||||
final Type returnType;
|
||||
final List<Arg> argsType;
|
||||
final bool isArray;
|
||||
final String annotation;
|
||||
|
||||
Func(this.name, this.returnType, this.argsType, this.isArray,
|
||||
[this.annotation = null]);
|
||||
}
|
||||
|
||||
class Arg {
|
||||
final String name;
|
||||
final Type type;
|
||||
final bool isArray;
|
||||
|
||||
Arg(this.name, this.type, this.isArray);
|
||||
}
|
6
lib/src/Resource/Template/TemplateType.dart
Normal file
6
lib/src/Resource/Template/TemplateType.dart
Normal file
@ -0,0 +1,6 @@
|
||||
enum TemplateType {
|
||||
Unspecified,
|
||||
Resource,
|
||||
Record,
|
||||
Wrapper,
|
||||
}
|
550
lib/src/Resource/Template/TypeTemplate.dart
Normal file
550
lib/src/Resource/Template/TypeTemplate.dart
Normal file
@ -0,0 +1,550 @@
|
||||
import 'dart:ffi';
|
||||
|
||||
import '../../Data/BinaryList.dart';
|
||||
import '../../Security/Integrity/SHA256.dart';
|
||||
|
||||
import '../../Data/IRecord.dart';
|
||||
import '../IResource.dart';
|
||||
import '../Warehouse.dart';
|
||||
import './TemplateDescriber.dart';
|
||||
|
||||
import './MemberTemplate.dart';
|
||||
import '../../Data/Guid.dart';
|
||||
import '../../Data/DC.dart';
|
||||
import './EventTemplate.dart';
|
||||
import './PropertyTemplate.dart';
|
||||
import './FunctionTemplate.dart';
|
||||
import '../StorageMode.dart';
|
||||
import 'ArgumentTemplate.dart';
|
||||
import 'TemplateDataType.dart';
|
||||
import 'TemplateType.dart';
|
||||
|
||||
class TypeTemplate {
|
||||
Guid _classId;
|
||||
String _className;
|
||||
List<MemberTemplate> _members = [];
|
||||
List<FunctionTemplate> _functions = [];
|
||||
List<EventTemplate> _events = [];
|
||||
List<PropertyTemplate> _properties = [];
|
||||
int _version;
|
||||
//bool isReady;
|
||||
|
||||
TemplateType _templateType;
|
||||
|
||||
DC _content;
|
||||
|
||||
DC get content => _content;
|
||||
|
||||
TemplateType get type => _templateType;
|
||||
|
||||
Type _definedType;
|
||||
|
||||
Type get definedType => _definedType;
|
||||
/*
|
||||
MemberTemplate getMemberTemplate(MemberInfo member)
|
||||
{
|
||||
if (member is MethodInfo)
|
||||
return getFunctionTemplate(member.Name);
|
||||
else if (member is EventInfo)
|
||||
return getEventTemplate(member.Name);
|
||||
else if (member is PropertyInfo)
|
||||
return getPropertyTemplate(member.Name);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
//@TODO: implement
|
||||
static List<TypeTemplate> getDependencies(TypeTemplate template) =>
|
||||
[];
|
||||
|
||||
EventTemplate getEventTemplateByName(String eventName) {
|
||||
for (var i in _events) if (i.name == eventName) return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
EventTemplate getEventTemplateByIndex(int index) {
|
||||
for (var i in _events) if (i.index == index) return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
FunctionTemplate getFunctionTemplateByName(String functionName) {
|
||||
for (var i in _functions) if (i.name == functionName) return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
FunctionTemplate getFunctionTemplateByIndex(int index) {
|
||||
for (var i in _functions) if (i.index == index) return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyTemplate getPropertyTemplateByIndex(int index) {
|
||||
for (var i in _properties) if (i.index == index) return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyTemplate getPropertyTemplateByName(String propertyName) {
|
||||
for (var i in _properties) if (i.name == propertyName) return i;
|
||||
return null;
|
||||
}
|
||||
|
||||
static Guid getTypeGuid(String typeName) {
|
||||
var tn = DC.stringToBytes(typeName);
|
||||
var hash = SHA256.compute(tn).clip(0, 16);
|
||||
return new Guid(hash);
|
||||
}
|
||||
|
||||
Guid get classId => _classId;
|
||||
|
||||
String get className => _className;
|
||||
|
||||
List<MemberTemplate> get methods => _members;
|
||||
|
||||
List<FunctionTemplate> get functions => _functions;
|
||||
|
||||
List<EventTemplate> get events => _events;
|
||||
|
||||
List<PropertyTemplate> get properties => _properties;
|
||||
|
||||
TypeTemplate.fromType(Type type, [bool addToWarehouse, bool isWrapper]) {
|
||||
var instance = Warehouse.createInstance(type);
|
||||
|
||||
if (instance is IRecord)
|
||||
_templateType = TemplateType.Record;
|
||||
else if (instance is IResource)
|
||||
_templateType = TemplateType.Resource;
|
||||
else
|
||||
throw new Exception("Type is neither a resource nor a record.");
|
||||
|
||||
TemplateDescriber describer = instance.template;
|
||||
|
||||
_definedType = type;
|
||||
|
||||
_className = describer.nameSpace;
|
||||
|
||||
// set guid
|
||||
_classId = getTypeGuid(_className);
|
||||
|
||||
if (addToWarehouse) Warehouse.putTemplate(this);
|
||||
// _templates.add(template.classId, template);
|
||||
|
||||
for (var i = 0; i < describer.properties.length; i++) {
|
||||
var pi = describer.properties[i];
|
||||
var pt = PropertyTemplate(
|
||||
this,
|
||||
i,
|
||||
pi.name,
|
||||
TemplateDataType.fromType(pi.type, pi.isArray),
|
||||
pi.readAnnotation,
|
||||
pi.writeAnnotation,
|
||||
0);
|
||||
properties.add(pt);
|
||||
}
|
||||
|
||||
for (var i = 0; i < describer.functions.length; i++) {
|
||||
var fi = describer.functions[i];
|
||||
|
||||
List<ArgumentTemplate> args = fi.argsType.map((arg) => ArgumentTemplate(
|
||||
arg.name, TemplateDataType.fromType(arg.type, arg.isArray)));
|
||||
|
||||
var ft = FunctionTemplate(this, i, fi.name, args,
|
||||
TemplateDataType.fromType(fi.returnType, fi.isArray), fi.annotation);
|
||||
|
||||
functions.add(ft);
|
||||
}
|
||||
|
||||
for (var i = 0; i < describer.events.length; i++) {
|
||||
var ei = describer.events[i];
|
||||
|
||||
var et = new EventTemplate(
|
||||
this,
|
||||
i,
|
||||
ei.name,
|
||||
TemplateDataType.fromType(ei.type, ei.isArray),
|
||||
ei.annotation,
|
||||
ei.listenable);
|
||||
|
||||
events.add(et);
|
||||
}
|
||||
|
||||
// append signals
|
||||
events.forEach(_members.add);
|
||||
// append slots
|
||||
functions.forEach(_members.add);
|
||||
// append properties
|
||||
properties.forEach(_members.add);
|
||||
|
||||
// bake it binarily
|
||||
var b = new BinaryList();
|
||||
b
|
||||
.addUint8(_templateType.index)
|
||||
.addGuid(classId)
|
||||
.addUint8(className.length)
|
||||
.addString(className)
|
||||
.addInt32(_version)
|
||||
.addUint16(_members.length);
|
||||
|
||||
functions.forEach((ft) => b.addDC(ft.compose()));
|
||||
properties.forEach((pt) => b.addDC(pt.compose()));
|
||||
events.forEach((et) => b.addDC(et.compose()));
|
||||
|
||||
_content = b.toDC();
|
||||
}
|
||||
|
||||
// static Guid getTypeGuid(Type type) => getTypeGuid(type.toString());
|
||||
|
||||
// static Guid getTypeGuid(String typeName)
|
||||
// {
|
||||
// var tn = Encoding.UTF8.GetBytes(typeName);
|
||||
// var hash = SHA256.Create().ComputeHash(tn).Clip(0, 16);
|
||||
|
||||
// return new Guid(hash);
|
||||
// }
|
||||
|
||||
// static Type GetElementType(Type type) => type switch
|
||||
// {
|
||||
// { IsArray: true } => type.GetElementType(),
|
||||
// { IsEnum: true } => type.GetEnumUnderlyingType(),
|
||||
// (_) => type
|
||||
// };
|
||||
|
||||
// static TypeTemplate[] GetRuntimeTypes(TypeTemplate template)
|
||||
// {
|
||||
|
||||
// List<TypeTemplate> list = [];
|
||||
|
||||
// list.add(template);
|
||||
|
||||
// var getRuntimeTypes = null;
|
||||
|
||||
// getRuntimeTypes = (TypeTemplate tmp, List<TypeTemplate> bag)
|
||||
// {
|
||||
// if (template.resourceType == null)
|
||||
// return;
|
||||
|
||||
// // functions
|
||||
// tmp.functions.foreach((f){
|
||||
|
||||
// var frtt = Warehouse.GetTemplate(getElementType(f.MethodInfo.ReturnType));
|
||||
// if (frtt != null)
|
||||
// {
|
||||
// if (!bag.Contains(frtt))
|
||||
// {
|
||||
// list.Add(frtt);
|
||||
// getRuntimeTypes(frtt, bag);
|
||||
// }
|
||||
// }
|
||||
|
||||
// var args = f.MethodInfo.GetParameters();
|
||||
|
||||
// for(var i = 0; i < args.Length - 1; i++)
|
||||
// {
|
||||
// var fpt = Warehouse.GetTemplate(GetElementType(args[i].ParameterType));
|
||||
// if (fpt != null)
|
||||
// {
|
||||
// if (!bag.Contains(fpt))
|
||||
// {
|
||||
// bag.Add(fpt);
|
||||
// getRuntimeTypes(fpt, bag);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // skip DistributedConnection argument
|
||||
// if (args.Length > 0)
|
||||
// {
|
||||
// var last = args.Last();
|
||||
// if (last.ParameterType != typeof(DistributedConnection))
|
||||
// {
|
||||
// var fpt = Warehouse.GetTemplate(GetElementType(last.ParameterType));
|
||||
// if (fpt != null)
|
||||
// {
|
||||
// if (!bag.Contains(fpt))
|
||||
// {
|
||||
// bag.Add(fpt);
|
||||
// getRuntimeTypes(fpt, bag);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// });
|
||||
|
||||
// // properties
|
||||
// foreach (var p in tmp.properties)
|
||||
// {
|
||||
// var pt = Warehouse.GetTemplate(GetElementType(p.PropertyInfo.PropertyType));
|
||||
// if (pt != null)
|
||||
// {
|
||||
// if (!bag.Contains(pt))
|
||||
// {
|
||||
// bag.Add(pt);
|
||||
// getRuntimeTypes(pt, bag);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // events
|
||||
// foreach (var e in tmp.events)
|
||||
// {
|
||||
// var et = Warehouse.GetTemplate(GetElementType(e.EventInfo.EventHandlerType.GenericTypeArguments[0]));
|
||||
|
||||
// if (et != null)
|
||||
// {
|
||||
// if (!bag.Contains(et))
|
||||
// {
|
||||
// bag.Add(et);
|
||||
// getRuntimeTypes(et, bag);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// getRuntimeTypes(template, list);
|
||||
// return list.ToArray();
|
||||
// }
|
||||
|
||||
// @TODO Create template from type
|
||||
// TypeTemplate.fromType(Type type) {
|
||||
|
||||
// }
|
||||
|
||||
/*
|
||||
TypeTemplate(Type type)
|
||||
{
|
||||
|
||||
type = ResourceProxy.GetBaseType(type);
|
||||
|
||||
// set guid
|
||||
|
||||
var typeName = Encoding.UTF8.GetBytes(type.FullName);
|
||||
var hash = SHA256.Create().ComputeHash(typeName).Clip(0, 16);
|
||||
|
||||
classId = new Guid(hash);
|
||||
className = type.FullName;
|
||||
|
||||
|
||||
#if NETSTANDARD1_5
|
||||
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
|
||||
|
||||
//byte currentIndex = 0;
|
||||
|
||||
byte i = 0;
|
||||
|
||||
foreach (var pi in propsInfo)
|
||||
{
|
||||
var ps = (ResourceProperty[])pi.GetCustomAttributes(typeof(ResourceProperty), true);
|
||||
if (ps.Length > 0)
|
||||
{
|
||||
var pt = new PropertyTemplate(this, i++, pi.Name, ps[0].ReadExpansion, ps[0].WriteExpansion, ps[0].Storage);
|
||||
pt.Info = pi;
|
||||
properties.Add(pt);
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
foreach (var ei in eventsInfo)
|
||||
{
|
||||
var es = (ResourceEvent[])ei.GetCustomAttributes(typeof(ResourceEvent), true);
|
||||
if (es.Length > 0)
|
||||
{
|
||||
var et = new EventTemplate(this, i++, ei.Name, es[0].Expansion);
|
||||
events.Add(et);
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
foreach (MethodInfo mi in methodsInfo)
|
||||
{
|
||||
var fs = (ResourceFunction[])mi.GetCustomAttributes(typeof(ResourceFunction), true);
|
||||
if (fs.Length > 0)
|
||||
{
|
||||
var ft = new FunctionTemplate(this, i++, mi.Name, mi.ReturnType == typeof(void), fs[0].Expansion);
|
||||
functions.Add(ft);
|
||||
}
|
||||
}
|
||||
|
||||
// append signals
|
||||
for (i = 0; i < events.Count; i++)
|
||||
members.Add(events[i]);
|
||||
// append slots
|
||||
for (i = 0; i < functions.Count; i++)
|
||||
members.Add(functions[i]);
|
||||
// append properties
|
||||
for (i = 0; i < properties.Count; i++)
|
||||
members.Add(properties[i]);
|
||||
|
||||
// bake it binarily
|
||||
var b = new BinaryList();
|
||||
b.AddGuid(classId)
|
||||
.AddUInt8((byte)className.Length)
|
||||
.AddString(className)
|
||||
.AddInt32(version)
|
||||
.AddUInt16((ushort)members.Count);
|
||||
|
||||
|
||||
foreach (var ft in functions)
|
||||
b.AddUInt8Array(ft.Compose());
|
||||
foreach (var pt in properties)
|
||||
b.AddUInt8Array(pt.Compose());
|
||||
foreach (var et in events)
|
||||
b.AddUInt8Array(et.Compose());
|
||||
|
||||
content = b.ToArray();
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
TypeTemplate.parse(DC data, [int offset = 0, int contentLength]) {
|
||||
// cool Dart feature
|
||||
contentLength ??= data.length;
|
||||
|
||||
int ends = offset + contentLength;
|
||||
|
||||
int oOffset = offset;
|
||||
|
||||
// start parsing...
|
||||
|
||||
//var od = new TypeTemplate();
|
||||
_content = data.clip(offset, contentLength);
|
||||
|
||||
_templateType = TemplateType.values[data.getUint8(offset++)];
|
||||
|
||||
_classId = data.getGuid(offset);
|
||||
offset += 16;
|
||||
_className = data.getString(offset + 1, data[offset]);
|
||||
offset += data[offset] + 1;
|
||||
|
||||
_version = data.getInt32(offset);
|
||||
offset += 4;
|
||||
|
||||
var methodsCount = data.getUint16(offset);
|
||||
offset += 2;
|
||||
|
||||
var functionIndex = 0;
|
||||
var propertyIndex = 0;
|
||||
var eventIndex = 0;
|
||||
|
||||
for (int i = 0; i < methodsCount; i++) {
|
||||
var type = data[offset] >> 5;
|
||||
|
||||
if (type == 0) // function
|
||||
{
|
||||
String expansion = null;
|
||||
var hasExpansion = ((data[offset++] & 0x10) == 0x10);
|
||||
|
||||
var name = data.getString(offset + 1, data[offset]);
|
||||
offset += data[offset] + 1;
|
||||
|
||||
var dt = TemplateDataType.parse(data, offset);
|
||||
offset += dt.size;
|
||||
|
||||
// arguments count
|
||||
var argsCount = data[offset++];
|
||||
List<ArgumentTemplate> arguments = [];
|
||||
|
||||
for (var a = 0; a < argsCount; a++) {
|
||||
var art = ArgumentTemplate.parse(data, offset);
|
||||
arguments.add(art.value);
|
||||
offset += art.size;
|
||||
}
|
||||
|
||||
if (hasExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.getUint32(offset);
|
||||
offset += 4;
|
||||
expansion = data.getString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var ft = new FunctionTemplate(
|
||||
this, functionIndex++, name, arguments, dt.value, expansion);
|
||||
|
||||
_functions.add(ft);
|
||||
} else if (type == 1) // property
|
||||
{
|
||||
String readExpansion = null, writeExpansion = null;
|
||||
|
||||
var hasReadExpansion = ((data[offset] & 0x8) == 0x8);
|
||||
var hasWriteExpansion = ((data[offset] & 0x10) == 0x10);
|
||||
var recordable = ((data[offset] & 1) == 1);
|
||||
var permission = (data[offset++] >> 1) & 0x3;
|
||||
var name = data.getString(offset + 1, data[offset]);
|
||||
|
||||
offset += data[offset] + 1;
|
||||
|
||||
var dt = TemplateDataType.parse(data, offset);
|
||||
|
||||
offset += dt.size;
|
||||
|
||||
if (hasReadExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.getUint32(offset);
|
||||
offset += 4;
|
||||
readExpansion = data.getString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
if (hasWriteExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.getUint32(offset);
|
||||
offset += 4;
|
||||
writeExpansion = data.getString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var pt = new PropertyTemplate(
|
||||
this,
|
||||
propertyIndex++,
|
||||
name,
|
||||
dt.value,
|
||||
readExpansion,
|
||||
writeExpansion,
|
||||
recordable ? StorageMode.Recordable : StorageMode.Volatile);
|
||||
|
||||
_properties.add(pt);
|
||||
} else if (type == 2) // Event
|
||||
{
|
||||
String expansion = null;
|
||||
var hasExpansion = ((data[offset] & 0x10) == 0x10);
|
||||
var listenable = ((data[offset++] & 0x8) == 0x8);
|
||||
|
||||
var name = data.getString(offset + 1, data[offset]);
|
||||
offset += data[offset] + 1;
|
||||
|
||||
var dt = TemplateDataType.parse(data, offset);
|
||||
|
||||
offset += dt.size;
|
||||
|
||||
if (hasExpansion) // expansion ?
|
||||
{
|
||||
var cs = data.getUint32(offset);
|
||||
offset += 4;
|
||||
expansion = data.getString(offset, cs);
|
||||
offset += cs;
|
||||
}
|
||||
|
||||
var et = new EventTemplate(
|
||||
this, eventIndex++, name, dt.value, expansion, listenable);
|
||||
|
||||
_events.add(et);
|
||||
}
|
||||
}
|
||||
|
||||
// append signals
|
||||
for (int i = 0; i < _events.length; i++) _members.add(_events[i]);
|
||||
// append slots
|
||||
for (int i = 0; i < _functions.length; i++) _members.add(_functions[i]);
|
||||
// append properties
|
||||
for (int i = 0; i < _properties.length; i++) _members.add(_properties[i]);
|
||||
}
|
||||
}
|
@ -23,7 +23,8 @@ SOFTWARE.
|
||||
*/
|
||||
|
||||
import '../Data/AutoList.dart';
|
||||
import './Template/ResourceTemplate.dart';
|
||||
import 'Template/TemplateType.dart';
|
||||
import 'Template/TypeTemplate.dart';
|
||||
import '../Data/Guid.dart';
|
||||
import '../Data/KeyList.dart';
|
||||
import '../Data/Structure.dart';
|
||||
@ -44,20 +45,30 @@ class Warehouse {
|
||||
static Map<int, IResource> _resources = new Map<int, IResource>();
|
||||
static int resourceCounter = 0;
|
||||
|
||||
static KeyList<Guid, ResourceTemplate> _templates =
|
||||
new KeyList<Guid, ResourceTemplate>();
|
||||
|
||||
static KeyList<TemplateType, KeyList<Guid, TypeTemplate>> _templates =
|
||||
_initTemplates(); //
|
||||
|
||||
//public delegate void StoreConnectedEvent(IStore store, string name);
|
||||
//public delegate void StoreDisconnectedEvent(IStore store);
|
||||
static _initTemplates() {
|
||||
var rt = new KeyList<TemplateType, KeyList<Guid, TypeTemplate>>();
|
||||
|
||||
//public static event StoreConnectedEvent StoreConnected;
|
||||
///public static event StoreDisconnectedEvent StoreDisconnected;
|
||||
rt.add(TemplateType.Unspecified, new KeyList<Guid, TypeTemplate>());
|
||||
rt.add(TemplateType.Resource, new KeyList<Guid, TypeTemplate>());
|
||||
rt.add(TemplateType.Record, new KeyList<Guid, TypeTemplate>());
|
||||
rt.add(TemplateType.Wrapper, new KeyList<Guid, TypeTemplate>());
|
||||
|
||||
static bool _warehouseIsOpen = false;
|
||||
return rt;
|
||||
}
|
||||
|
||||
|
||||
static KeyList<Type, Function()> _factory = _getBuiltInTypes();
|
||||
|
||||
static KeyList<String, AsyncReply<IStore> Function(String, dynamic)>
|
||||
protocols = _getSupportedProtocols();
|
||||
|
||||
|
||||
static bool _warehouseIsOpen = false;
|
||||
|
||||
static final _urlRegex = RegExp(r'^(?:([^\s|:]*):\/\/([^\/]*)\/?(.*))');
|
||||
|
||||
/// <summary>
|
||||
@ -162,7 +173,7 @@ class Warehouse {
|
||||
|
||||
static List<IResource> qureyIn(
|
||||
List<String> path, int index, AutoList<IResource, Instance> resources) {
|
||||
var rt = new List<IResource>();
|
||||
List<IResource> rt = [];
|
||||
|
||||
if (index == path.length - 1) {
|
||||
if (path[index] == "")
|
||||
@ -206,11 +217,11 @@ class Warehouse {
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <returns>Resource instance.</returns>
|
||||
static AsyncReply<dynamic> get(String path,
|
||||
static AsyncReply<T> get<T extends IResource>(String path,
|
||||
[attributes = null,
|
||||
IResource parent = null,
|
||||
IPermissionsManager manager = null]) {
|
||||
var rt = AsyncReply<IResource>();
|
||||
var rt = AsyncReply<T>();
|
||||
|
||||
// Should we create a new store ?
|
||||
if (_urlRegex.hasMatch(path)) {
|
||||
@ -226,7 +237,7 @@ class Warehouse {
|
||||
rt.trigger(r);
|
||||
}).error((e) => rt.triggerError(e));
|
||||
else
|
||||
rt.trigger(store);
|
||||
rt.trigger(store as T);
|
||||
}).error((e) {
|
||||
rt.triggerError(e);
|
||||
//Warehouse.remove(store);
|
||||
@ -333,14 +344,74 @@ class Warehouse {
|
||||
/// <param name="name">Resource name.</param>
|
||||
/// <param name="store">IStore that manages the resource. Can be null if the resource is a store.</param>
|
||||
/// <param name="parent">Parent resource. if not presented the store becomes the parent for the resource.</param>
|
||||
static AsyncReply<bool> put(IResource resource, String name,
|
||||
static AsyncReply<T> put<T extends IResource>(String name, T resource,
|
||||
[IStore store = null,
|
||||
IResource parent = null,
|
||||
ResourceTemplate customTemplate = null,
|
||||
TypeTemplate customTemplate = null,
|
||||
int age = 0,
|
||||
IPermissionsManager manager = null,
|
||||
attributes = null]) {
|
||||
var rt = AsyncReply<bool>();
|
||||
var rt = AsyncReply<T>();
|
||||
|
||||
if (resource.instance != null) {
|
||||
rt.triggerError(Exception("Resource has a store."));
|
||||
return rt;
|
||||
}
|
||||
|
||||
// @TODO: Trim left '/' char
|
||||
// var path = name.trimLeft().split("/");
|
||||
// if (path.length > 1)
|
||||
// {
|
||||
// if (parent != null)
|
||||
// rt.triggerError(Exception("Parent can't be set when using path in instance name"));
|
||||
|
||||
// Warehouse.get<IResource>(path.take(path.length - 1).join("/")).then((value){
|
||||
// if (value == null)
|
||||
// rt.triggerError(Exception("Can't find parent"));
|
||||
|
||||
// parent = value;
|
||||
|
||||
// store = store ?? parent.instance.store;
|
||||
|
||||
// var instanceName = path.last;
|
||||
|
||||
// if (store == null)
|
||||
// {
|
||||
// // assign parent as a store
|
||||
// if (parent is IStore)
|
||||
// {
|
||||
// store = (IStore)parent;
|
||||
// stores
|
||||
// List<WeakReference<IResource>> list;
|
||||
// if (stores.TryGetValue(store, out list))
|
||||
// lock (((ICollection)list).SyncRoot)
|
||||
// list.Add(resourceReference);
|
||||
// //stores[store].Add(resourceReference);
|
||||
// }
|
||||
// // assign parent's store as a store
|
||||
// else if (parent != null)
|
||||
// {
|
||||
// store = parent.instance.store;
|
||||
|
||||
// List<WeakReference<IResource>> list;
|
||||
// if (stores.TryGetValue(store, out list))
|
||||
// lock (((ICollection)list).SyncRoot)
|
||||
// list.Add(resourceReference);
|
||||
|
||||
// //stores[store].Add(resourceReference);
|
||||
// }
|
||||
// // assign self as a store (root store)
|
||||
// else if (resource is IStore)
|
||||
// {
|
||||
// store = resource;
|
||||
// }
|
||||
// else
|
||||
// throw new Exception("Can't find a store for the resource.");
|
||||
// }
|
||||
|
||||
// });
|
||||
|
||||
// }
|
||||
|
||||
resource.instance = new Instance(
|
||||
resourceCounter++, name, resource, store, customTemplate, age);
|
||||
@ -364,11 +435,17 @@ class Warehouse {
|
||||
resource.trigger(ResourceTrigger.Initialize).then<dynamic>((value) {
|
||||
if (resource is IStore)
|
||||
resource.trigger(ResourceTrigger.Open).then<dynamic>((value) {
|
||||
rt.trigger(value);
|
||||
}).error((ex) => rt.triggerError(ex));
|
||||
rt.trigger(resource);
|
||||
}).error((ex) {
|
||||
Warehouse.remove(resource);
|
||||
rt.triggerError(ex);
|
||||
});
|
||||
else
|
||||
rt.trigger(value);
|
||||
}).error((ex) => rt.triggerError(ex));
|
||||
rt.trigger(resource);
|
||||
}).error((ex) {
|
||||
Warehouse.remove(resource);
|
||||
rt.triggerError(ex);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -380,8 +457,11 @@ class Warehouse {
|
||||
if (value)
|
||||
initResource();
|
||||
else
|
||||
rt.trigger(false);
|
||||
}).error((ex) => rt.triggerError(ex));
|
||||
rt.trigger(null);
|
||||
}).error((ex) {
|
||||
Warehouse.remove(resource);
|
||||
rt.triggerError(ex);
|
||||
});
|
||||
}
|
||||
|
||||
// return new name
|
||||
@ -389,12 +469,18 @@ class Warehouse {
|
||||
return rt;
|
||||
}
|
||||
|
||||
static AsyncReply<T> New<T extends IResource>(T resource, String name,
|
||||
static T createInstance<T>(Type T) {
|
||||
return _factory[T].call();
|
||||
}
|
||||
|
||||
static AsyncReply<T> newResource<T extends IResource>(String name,
|
||||
[IStore store = null,
|
||||
IResource parent = null,
|
||||
IPermissionsManager manager = null,
|
||||
attributes = null,
|
||||
properties = null]) {
|
||||
var resource = _factory[T].call();
|
||||
|
||||
if (properties != null) {
|
||||
dynamic d = resource;
|
||||
|
||||
@ -405,9 +491,9 @@ class Warehouse {
|
||||
|
||||
var rt = AsyncReply<T>();
|
||||
|
||||
put(resource, name, store, parent, null, 0, manager, attributes)
|
||||
.then<bool>((value) {
|
||||
if (value)
|
||||
put<T>(name, resource, store, parent, null, 0, manager, attributes)
|
||||
.then<IResource>((value) {
|
||||
if (value != null)
|
||||
rt.trigger(resource);
|
||||
else
|
||||
rt.trigger(null);
|
||||
@ -427,49 +513,77 @@ class Warehouse {
|
||||
/// Put a resource template in the templates warehouse.
|
||||
/// </summary>
|
||||
/// <param name="template">Resource template.</param>
|
||||
static void putTemplate(ResourceTemplate template) {
|
||||
if (!_templates.containsKey(template.classId))
|
||||
_templates.add(template.classId, template);
|
||||
static void putTemplate(TypeTemplate template) {
|
||||
_templates[template.type][template.classId] = template;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a template by type from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
|
||||
/// Get a template by type from the templates warehouse. If not in the warehouse, a new TypeTemplate is created and added to the warehouse.
|
||||
/// </summary>
|
||||
/// <param name="type">.Net type.</param>
|
||||
/// <returns>Resource template.</returns>
|
||||
static ResourceTemplate getTemplateByType(Type type) {
|
||||
static TypeTemplate getTemplateByType(Type type) {
|
||||
// loaded ?
|
||||
for (var t in _templates.values)
|
||||
if (t.className == type.toString()) return t;
|
||||
for (var tmps in _templates.values)
|
||||
for (var tmp in tmps.values)
|
||||
if (tmp.className == type.toString()) return tmp;
|
||||
|
||||
var template = new ResourceTemplate.fromType(type);
|
||||
_templates.add(template.classId, template);
|
||||
var template = new TypeTemplate.fromType(type, true);
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a template by class Id from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
|
||||
/// Get a template by class Id from the templates warehouse. If not in the warehouse, a new TypeTemplate is created and added to the warehouse.
|
||||
/// </summary>
|
||||
/// <param name="classId">Class Id.</param>
|
||||
/// <returns>Resource template.</returns>
|
||||
static AsyncReply<ResourceTemplate> getTemplateByClassId(Guid classId) {
|
||||
if (_templates.containsKey(classId))
|
||||
return new AsyncReply<ResourceTemplate>.ready(_templates[classId]);
|
||||
return null;
|
||||
static TypeTemplate getTemplateByClassId(Guid classId,
|
||||
[TemplateType templateType = TemplateType.Unspecified]) {
|
||||
if (templateType == TemplateType.Unspecified) {
|
||||
// look in resources
|
||||
var template = _templates[TemplateType.Resource][classId];
|
||||
if (template != null) return template;
|
||||
|
||||
// look in records
|
||||
template = _templates[TemplateType.Record][classId];
|
||||
if (template != null) return template;
|
||||
|
||||
// look in wrappers
|
||||
template = _templates[TemplateType.Wrapper][classId];
|
||||
return template;
|
||||
} else {
|
||||
return _templates[templateType][classId];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a template by class name from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
|
||||
/// Get a template by class name from the templates warehouse. If not in the warehouse, a new TypeTemplate is created and added to the warehouse.
|
||||
/// </summary>
|
||||
/// <param name="className">Class name.</param>
|
||||
/// <returns>Resource template.</returns>
|
||||
static AsyncReply<ResourceTemplate> getTemplateByClassName(String className) {
|
||||
for (var t in _templates.values)
|
||||
if (t.className == className)
|
||||
return new AsyncReply<ResourceTemplate>.ready(t);
|
||||
static TypeTemplate getTemplateByClassName(String className, [TemplateType templateType = TemplateType.Unspecified]) {
|
||||
|
||||
return null;
|
||||
if (templateType == TemplateType.Unspecified)
|
||||
{
|
||||
// look in resources
|
||||
var template = _templates[TemplateType.Resource].values.firstWhere((x) => x.className == className);
|
||||
if (template != null)
|
||||
return template;
|
||||
|
||||
// look in records
|
||||
template = _templates[TemplateType.Record].values.firstWhere((x) => x.className == className);
|
||||
if (template != null)
|
||||
return template;
|
||||
|
||||
// look in wrappers
|
||||
template = _templates[TemplateType.Wrapper].values.firstWhere((x) => x.className == className);
|
||||
return template;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _templates[templateType].values.firstWhere((x) => x.className == className);
|
||||
}
|
||||
}
|
||||
|
||||
static bool remove(IResource resource) {
|
||||
@ -505,8 +619,15 @@ class Warehouse {
|
||||
new KeyList<String, AsyncReply<IStore> Function(String, dynamic)>();
|
||||
rt.add(
|
||||
"iip",
|
||||
(String name, attributes) => Warehouse.New<DistributedConnection>(
|
||||
DistributedConnection(), name, null, null, null, attributes));
|
||||
(String name, attributes) =>
|
||||
Warehouse.newResource<DistributedConnection>(
|
||||
name, null, null, null, attributes));
|
||||
return rt;
|
||||
}
|
||||
|
||||
static KeyList<Type, Function()> _getBuiltInTypes() {
|
||||
var rt = KeyList<Type, Function()>();
|
||||
rt.add(DistributedConnection, () => DistributedConnection());
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user