2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2026-01-27 01:20:39 +00:00

Annotations

This commit is contained in:
2026-01-19 18:38:34 +03:00
parent 74a71a32f1
commit 63ba506338
8 changed files with 157 additions and 48 deletions

View File

@@ -11,6 +11,7 @@ using Esiur.Net.IIP;
using System.Diagnostics; using System.Diagnostics;
namespace Esiur.Proxy; namespace Esiur.Proxy;
public static class TemplateGenerator public static class TemplateGenerator
{ {
internal static Regex urlRegex = new Regex(@"^(?:([\S]*)://([^/]*)/?)"); internal static Regex urlRegex = new Regex(@"^(?:([\S]*)://([^/]*)/?)");
@@ -300,8 +301,13 @@ public static class TemplateGenerator
var positionalArgs = f.Arguments.Where((x) => !x.Optional).ToArray(); var positionalArgs = f.Arguments.Where((x) => !x.Optional).ToArray();
var optionalArgs = f.Arguments.Where((x) => x.Optional).ToArray(); var optionalArgs = f.Arguments.Where((x) => x.Optional).ToArray();
if (f.Annotation != null) if (f.Annotations != null)
rt.AppendLine($"[Annotation({ToLiteral(f.Annotation)})]"); {
foreach (var kv in f.Annotations)
{
rt.AppendLine($"[Annotation({ToLiteral(kv.Key)}, {ToLiteral(kv.Value)})]");
}
}
if (f.IsStatic) if (f.IsStatic)
{ {

View File

@@ -4,17 +4,26 @@ using System.Text;
namespace Esiur.Resource; namespace Esiur.Resource;
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Event)] [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Event, AllowMultiple = true)]
public class AnnotationAttribute : Attribute public class AnnotationAttribute : Attribute
{ {
public string Annotation { get; set; } public readonly string? Key;
public readonly string Value;
public AnnotationAttribute(string annotation) public AnnotationAttribute(string annotation)
{ {
this.Annotation = annotation; Key = null;
Value = annotation;
} }
public AnnotationAttribute(params string[] annotations) public AnnotationAttribute(string key, string value)
{ {
this.Annotation = String.Join("\n", annotations); Key = key;
Value = value;
} }
//public AnnotationAttribute(params string[] annotations)
//{
// this.Annotation = String.Join("\n", annotations);
//}
} }

View File

@@ -5,6 +5,7 @@ using System.Text;
using System.Reflection; using System.Reflection;
namespace Esiur.Resource.Template; namespace Esiur.Resource.Template;
public class ArgumentTemplate public class ArgumentTemplate
{ {
public string Name { get; set; } public string Name { get; set; }
@@ -17,16 +18,32 @@ public class ArgumentTemplate
public int Index { get; set; } public int Index { get; set; }
public Map<string, string> Annotations { get; set; }
public static (uint, ArgumentTemplate) Parse(byte[] data, uint offset, int index) public static (uint, ArgumentTemplate) Parse(byte[] data, uint offset, int index)
{ {
var optional = (data[offset++] & 0x1) == 0x1; var optional = (data[offset] & 0x1) == 0x1;
var hasAnnotations = (data[offset++] & 0x2) == 0x2;
var cs = (uint)data[offset++]; var cs = (uint)data[offset++];
var name = data.GetString(offset, cs); var name = data.GetString(offset, cs);
offset += cs; offset += cs;
var (size, type) = TRU.Parse(data, offset); var (size, type) = TRU.Parse(data, offset);
return (cs + 2 + size, new ArgumentTemplate(name, index, type, optional));
Map<string, string> annotations = null;
if (hasAnnotations)
{
var acs = data.GetUInt32(offset, Endian.Little);
offset += 2;
var (l, a) = Codec.ParseSync(data, offset, null);
// for saftey, Map<string, string> might change in the future
if (a is Map<string, string> ann)
annotations = ann;
}
return (cs + 2 + size, new ArgumentTemplate(name, index, type, optional, annotations));
} }
public ArgumentTemplate() public ArgumentTemplate()
@@ -34,18 +51,29 @@ public class ArgumentTemplate
} }
public ArgumentTemplate(string name, int index, TRU type, bool optional) public ArgumentTemplate(string name, int index, TRU type, bool optional, Map<string, string> annotations)
{ {
Name = name; Name = name;
Index = index; Index = index;
Type = type; Type = type;
Optional = optional; Optional = optional;
Annotations = annotations;
}
public override string ToString()
{
if (Optional)
return $"[{Name}: {Type}]";
else
return $"{Name}: {Type} ";
} }
public byte[] Compose() public byte[] Compose()
{ {
var name = DC.ToBytes(Name); var name = DC.ToBytes(Name);
if (Annotations == null)
{
return new BinaryList() return new BinaryList()
.AddUInt8(Optional ? (byte)1 : (byte)0) .AddUInt8(Optional ? (byte)1 : (byte)0)
.AddUInt8((byte)name.Length) .AddUInt8((byte)name.Length)
@@ -53,4 +81,19 @@ public class ArgumentTemplate
.AddUInt8Array(Type.Compose()) .AddUInt8Array(Type.Compose())
.ToArray(); .ToArray();
} }
else
{
var exp = Codec.Compose(Annotations, null, null);
return new BinaryList()
.AddUInt8((byte)(0x2 | (Optional ? 1 : 0)))
.AddUInt8((byte)name.Length)
.AddUInt8Array(name)
.AddUInt8Array(Type.Compose())
.AddUInt32((ushort)exp.Length)
.AddUInt8Array(exp)
.ToArray();
}
}
} }

View File

@@ -7,6 +7,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Esiur.Resource.Template; namespace Esiur.Resource.Template;
public class AttributeTemplate : MemberTemplate public class AttributeTemplate : MemberTemplate
{ {
public PropertyInfo PropertyInfo public PropertyInfo PropertyInfo

View File

@@ -10,16 +10,16 @@ namespace Esiur.Resource.Template;
public class ConstantTemplate : MemberTemplate public class ConstantTemplate : MemberTemplate
{ {
public readonly object Value; public readonly object Value;
//public readonly byte[] ValueData;
public readonly string Annotation; public Map<string, string> Annotations;
public readonly TRU ValueType; public readonly TRU ValueType;
public FieldInfo FieldInfo { get; set; } public FieldInfo FieldInfo { get; set; }
public ConstantTemplate(TypeTemplate template, byte index, string name, bool inherited, TRU valueType, object value, string annotation) public ConstantTemplate(TypeTemplate template, byte index, string name, bool inherited, TRU valueType, object value, Map<string, string> annotations)
: base(template, index, name, inherited) : base(template, index, name, inherited)
{ {
Annotation = annotation; Annotations = annotations;
ValueType = valueType; ValueType = valueType;
Value = value; Value = value;
//try //try
@@ -40,9 +40,9 @@ public class ConstantTemplate : MemberTemplate
var hdr = Inherited ? (byte)0x80 : (byte)0; var hdr = Inherited ? (byte)0x80 : (byte)0;
if (Annotation != null) if (Annotations != null)
{ {
var exp = DC.ToBytes(Annotation); var exp = Codec.Compose(Annotations, null, null);// DC.ToBytes(Annotation);
hdr |= 0x70; hdr |= 0x70;
return new BinaryList() return new BinaryList()
.AddUInt8(hdr) .AddUInt8(hdr)
@@ -71,7 +71,7 @@ public class ConstantTemplate : MemberTemplate
public static ConstantTemplate MakeConstantTemplate(Type type, FieldInfo ci, byte index = 0, string customName = null, TypeTemplate typeTemplate = null) public static ConstantTemplate MakeConstantTemplate(Type type, FieldInfo ci, byte index = 0, string customName = null, TypeTemplate typeTemplate = null)
{ {
var annotationAttr = ci.GetCustomAttribute<AnnotationAttribute>(true); var annotationAttrs = ci.GetCustomAttributes<AnnotationAttribute>(true);
var valueType = TRU.FromType(ci.FieldType); var valueType = TRU.FromType(ci.FieldType);
@@ -83,7 +83,17 @@ public class ConstantTemplate : MemberTemplate
if (typeTemplate?.Type == TemplateType.Enum) if (typeTemplate?.Type == TemplateType.Enum)
value = Convert.ChangeType(value, ci.FieldType.GetEnumUnderlyingType()); value = Convert.ChangeType(value, ci.FieldType.GetEnumUnderlyingType());
var ct = new ConstantTemplate(typeTemplate, index, customName ?? ci.Name, ci.DeclaringType != type, valueType, value, annotationAttr?.Annotation); Map<string, string> annotations = null;
if (annotationAttrs != null && annotationAttrs.Count() > 0)
{
annotations = new Map<string, string>();
foreach (var attr in annotationAttrs)
annotations.Add(attr.Key, attr.Value);
}
var ct = new ConstantTemplate(typeTemplate, index, customName ?? ci.Name, ci.DeclaringType != type, valueType, value, annotations);
ct.FieldInfo = ci; ct.FieldInfo = ci;
return ct; return ct;

View File

@@ -9,14 +9,20 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Esiur.Resource.Template; namespace Esiur.Resource.Template;
public class EventTemplate : MemberTemplate public class EventTemplate : MemberTemplate
{ {
public string Annotation public Map<string, string> Annotations
{ {
get; get;
set; set;
} }
public override string ToString()
{
return $"{Name}: {ArgumentType}";
}
public bool Subscribable { get; set; } public bool Subscribable { get; set; }
public EventInfo EventInfo { get; set; } public EventInfo EventInfo { get; set; }
@@ -32,9 +38,9 @@ public class EventTemplate : MemberTemplate
if (Subscribable) if (Subscribable)
hdr |= 0x8; hdr |= 0x8;
if (Annotation != null) if (Annotations != null)
{ {
var exp = DC.ToBytes(Annotation); var exp = Codec.Compose(Annotations, null, null); //( DC.ToBytes(Annotation);
hdr |= 0x50; hdr |= 0x50;
return new BinaryList() return new BinaryList()
.AddUInt8(hdr) .AddUInt8(hdr)
@@ -47,6 +53,7 @@ public class EventTemplate : MemberTemplate
} }
else else
hdr |= 0x40; hdr |= 0x40;
return new BinaryList() return new BinaryList()
.AddUInt8(hdr) .AddUInt8(hdr)
.AddUInt8((byte)name.Length) .AddUInt8((byte)name.Length)
@@ -55,10 +62,10 @@ public class EventTemplate : MemberTemplate
.ToArray(); .ToArray();
} }
public EventTemplate(TypeTemplate template, byte index, string name, bool inherited, TRU argumentType, string annotation = null, bool subscribable = false) public EventTemplate(TypeTemplate template, byte index, string name, bool inherited, TRU argumentType, Map<string, string> annotations = null, bool subscribable = false)
: base(template, index, name, inherited) : base(template, index, name, inherited)
{ {
this.Annotation = annotation; this.Annotations = annotations;
this.Subscribable = subscribable; this.Subscribable = subscribable;
this.ArgumentType = argumentType; this.ArgumentType = argumentType;
} }
@@ -80,7 +87,7 @@ public class EventTemplate : MemberTemplate
if (evtType == null) if (evtType == null)
throw new Exception($"Unsupported type `{argType}` in event `{type.Name}.{ei.Name}`"); throw new Exception($"Unsupported type `{argType}` in event `{type.Name}.{ei.Name}`");
var annotationAttr = ei.GetCustomAttribute<AnnotationAttribute>(true); var annotationAttrs = ei.GetCustomAttributes<AnnotationAttribute>(true);
var subscribableAttr = ei.GetCustomAttribute<SubscribableAttribute>(true); var subscribableAttr = ei.GetCustomAttribute<SubscribableAttribute>(true);
//evtType.Nullable = new NullabilityInfoContext().Create(ei).ReadState is NullabilityState.Nullable; //evtType.Nullable = new NullabilityInfoContext().Create(ei).ReadState is NullabilityState.Nullable;
@@ -117,8 +124,13 @@ public class EventTemplate : MemberTemplate
var et = new EventTemplate(typeTemplate, index, customName ?? ei.Name, ei.DeclaringType != type, evtType); var et = new EventTemplate(typeTemplate, index, customName ?? ei.Name, ei.DeclaringType != type, evtType);
et.EventInfo = ei; et.EventInfo = ei;
if (annotationAttr != null)
et.Annotation = annotationAttr.Annotation; if (annotationAttrs != null && annotationAttrs.Count() > 0)
{
et.Annotations = new Map<string, string>();
foreach (var attr in annotationAttrs)
et.Annotations.Add(attr.Key, attr.Value);
}
if (subscribableAttr != null) if (subscribableAttr != null)
et.Subscribable = true; et.Subscribable = true;

View File

@@ -13,7 +13,7 @@ namespace Esiur.Resource.Template;
public class FunctionTemplate : MemberTemplate public class FunctionTemplate : MemberTemplate
{ {
public string Annotation public Map<string, string> Annotations
{ {
get; get;
set; set;
@@ -53,9 +53,9 @@ public class FunctionTemplate : MemberTemplate
bl.AddUInt8Array(Arguments[i].Compose()); bl.AddUInt8Array(Arguments[i].Compose());
if (Annotation != null) if (Annotations != null)
{ {
var exp = DC.ToBytes(Annotation); var exp = Codec.Compose(Annotations, null, null);// DC.ToBytes(Annotation);
bl.AddInt32(exp.Length) bl.AddInt32(exp.Length)
.AddUInt8Array(exp); .AddUInt8Array(exp);
bl.InsertUInt8(0, (byte)((Inherited ? (byte)0x90 : (byte)0x10) | (IsStatic ? 0x4 : 0))); bl.InsertUInt8(0, (byte)((Inherited ? (byte)0x90 : (byte)0x10) | (IsStatic ? 0x4 : 0)));
@@ -66,12 +66,12 @@ public class FunctionTemplate : MemberTemplate
return bl.ToArray(); return bl.ToArray();
} }
public FunctionTemplate(TypeTemplate template, byte index, string name, bool inherited, bool isStatic, ArgumentTemplate[] arguments, TRU returnType, string annotation = null) public FunctionTemplate(TypeTemplate template, byte index, string name, bool inherited, bool isStatic, ArgumentTemplate[] arguments, TRU returnType, Map<string, string> annotations = null)
: base(template, index, name, inherited) : base(template, index, name, inherited)
{ {
this.Arguments = arguments; this.Arguments = arguments;
this.ReturnType = returnType; this.ReturnType = returnType;
this.Annotation = annotation; this.Annotations = annotations;
this.IsStatic = isStatic; this.IsStatic = isStatic;
} }
@@ -105,7 +105,7 @@ public class FunctionTemplate : MemberTemplate
if (rtType == null) if (rtType == null)
throw new Exception($"Unsupported type `{mi.ReturnType}` in method `{type.Name}.{mi.Name}` return"); throw new Exception($"Unsupported type `{mi.ReturnType}` in method `{type.Name}.{mi.Name}` return");
var annotationAttr = mi.GetCustomAttribute<AnnotationAttribute>(true); var annotationAttrs = mi.GetCustomAttributes<AnnotationAttribute>(true);
//var nullabilityInfoContext = new NullabilityInfoContext(); //var nullabilityInfoContext = new NullabilityInfoContext();
//rtType.Nullable = nullabilityInfoContext.Create(mi.ReturnParameter).WriteState is NullabilityState.Nullable; //rtType.Nullable = nullabilityInfoContext.Create(mi.ReturnParameter).WriteState is NullabilityState.Nullable;
@@ -174,17 +174,13 @@ public class FunctionTemplate : MemberTemplate
if (argType == null) if (argType == null)
throw new Exception($"Unsupported type `{x.ParameterType}` in method `{type.Name}.{mi.Name}` parameter `{x.Name}`"); throw new Exception($"Unsupported type `{x.ParameterType}` in method `{type.Name}.{mi.Name}` parameter `{x.Name}`");
//argType.Nullable = nullabilityInfoContext.Create(x).WriteState is NullabilityState.Nullable;
//var argNullableAttr = x.GetCustomAttribute<NullableAttribute>(true); var argAnnotationAttrs = x.GetCustomAttributes<AnnotationAttribute>(true);
//var argNullableContextAttr = x.GetCustomAttribute<NullableContextAttribute>(true) ?? nullableContextAttr;
var argNullableAttr = x.GetCustomAttributes(true).FirstOrDefault(x => x.GetType().FullName == "System.Runtime.CompilerServices.NullableAttribute"); var argNullableAttr = x.GetCustomAttributes(true).FirstOrDefault(x => x.GetType().FullName == "System.Runtime.CompilerServices.NullableAttribute");
var argNullableContextAttr = x.GetCustomAttributes(true).FirstOrDefault(x => x.GetType().FullName == "System.Runtime.CompilerServices.NullableContextAttr"); var argNullableContextAttr = x.GetCustomAttributes(true).FirstOrDefault(x => x.GetType().FullName == "System.Runtime.CompilerServices.NullableContextAttr");
//var argFlags = argNullableAttr?.Flags?.ToList() ?? new List<byte>();
//var argFlags = ((byte[])argNullableAttr?.NullableFlags ?? new byte[0]).ToList();
var argNullableAttrFlags = (argNullableAttr?.GetType().GetField("NullableFlags")?.GetValue(argNullableAttr) as byte[] ?? new byte[0]).ToList(); var argNullableAttrFlags = (argNullableAttr?.GetType().GetField("NullableFlags")?.GetValue(argNullableAttr) as byte[] ?? new byte[0]).ToList();
var argNullableContextAttrFlag = (byte)(argNullableAttr?.GetType().GetField("Flag")?.GetValue(argNullableAttr) ?? (byte)0); var argNullableContextAttrFlag = (byte)(argNullableAttr?.GetType().GetField("Flag")?.GetValue(argNullableAttr) ?? (byte)0);
@@ -203,12 +199,22 @@ public class FunctionTemplate : MemberTemplate
argType.SetNull(argNullableAttrFlags); argType.SetNull(argNullableAttrFlags);
} }
Map<string, string> argAnn = null;
if (argAnnotationAttrs != null && argAnnotationAttrs.Count() > 0)
{
argAnn = new Map<string, string>();
foreach (var attr in argAnnotationAttrs)
argAnn.Add(attr.Key, attr.Value);
}
return new ArgumentTemplate() return new ArgumentTemplate()
{ {
Name = x.Name, Name = x.Name,
Type = argType, Type = argType,
ParameterInfo = x, ParameterInfo = x,
Optional = x.IsOptional Optional = x.IsOptional,
Annotations = argAnn
}; };
}) })
.ToArray(); .ToArray();
@@ -219,10 +225,21 @@ public class FunctionTemplate : MemberTemplate
mi.IsStatic, mi.IsStatic,
arguments, rtType); arguments, rtType);
if (annotationAttr != null)
ft.Annotation = annotationAttr.Annotation; if (annotationAttrs != null && annotationAttrs.Count() > 0)
{
ft.Annotations = new Map<string, string>();
foreach (var attr in annotationAttrs)
ft.Annotations.Add(attr.Key, attr.Value);
}
else else
ft.Annotation = "(" + String.Join(",", mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection)).Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name; {
ft.Annotations = new Map<string, string>();
ft.Annotations.Add(null, "(" + String.Join(",",
mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection))
.Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name);
}
ft.MethodInfo = mi; ft.MethodInfo = mi;
// functions.Add(ft); // functions.Add(ft);
@@ -230,4 +247,11 @@ public class FunctionTemplate : MemberTemplate
return ft; return ft;
} }
public override string ToString()
{
//return = "(" + String.Join(",", mi.GetParameters().Where(x => x.ParameterType != typeof(DistributedConnection)).Select(x => "[" + x.ParameterType.Name + "] " + x.Name)) + ") -> " + mi.ReturnType.Name;
return $"{ReturnType} {Name}({string.Join(", ", Arguments.Select(a => a.ToString()))})";
}
} }

View File

@@ -76,6 +76,10 @@ public class PropertyTemplate : MemberTemplate
set; set;
}*/ }*/
public override string ToString()
{
return $"{Name}: {ValueType}";
}
public override byte[] Compose() public override byte[] Compose()
{ {