2
0
mirror of https://github.com/esiur/esiur-dart.git synced 2026-04-02 09:38:20 +00:00
This commit is contained in:
2021-07-14 05:16:40 +03:00
parent 7971c836b7
commit 737397da11
50 changed files with 6238 additions and 4926 deletions

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

View File

@@ -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) {}
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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]);
}
}

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

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

View File

@@ -0,0 +1,6 @@
enum TemplateType {
Unspecified,
Resource,
Record,
Wrapper,
}

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