diff --git a/BeefLibs/corlib/src/Reflection/AttributeInfo.bf b/BeefLibs/corlib/src/Reflection/AttributeInfo.bf index 6efb63e5..201ff0a8 100644 --- a/BeefLibs/corlib/src/Reflection/AttributeInfo.bf +++ b/BeefLibs/corlib/src/Reflection/AttributeInfo.bf @@ -1,3 +1,4 @@ +using System.Collections; namespace System.Reflection { class AttributeInfo @@ -112,5 +113,237 @@ namespace System.Reflection return .Err; } + + public struct CustomAttributeEnumerator : IEnumerator, IDisposable + { + void* data; + int32 attrIdx; + uint8 count; + Object targetAttr; + + public this(void* inAttrData) + { + data = inAttrData; + data++; + attrIdx = 0; + count = data != null ? AttributeInfo.Decode!(data) : 0; + targetAttr = null; + } + + public Object Current + { + get + { + return targetAttr; + } + } + + public bool MoveNext() mut + { + if (attrIdx >= count || data == null) + return false; + + void* startPtr = data; + var len = AttributeInfo.Decode!(data); + void* endPtr = (uint8*)startPtr + len; + + var typeId = AttributeInfo.Decode!(data); + + var methodIdx = AttributeInfo.Decode!(data); + + Type attrType = Type.[Friend]GetType(typeId); + TypeInstance attrTypeInst = attrType as TypeInstance; + MethodInfo methodInfo = .(attrTypeInst, attrTypeInst.[Friend]mMethodDataPtr + methodIdx); + + Object[] args = scope Object[methodInfo.[Friend]mData.mMethodData.mParamCount]; + + int argIdx = 0; + while (data < endPtr) + { + var attrDataType = AttributeInfo.Decode!(data); + switch (attrDataType) + { + case .Int8, + .UInt8, + .Char8, + .Boolean: + let attrData = AttributeInfo.Decode!(data); + args[argIdx] = scope:: box attrData; + case .Int16, + .UInt16, + .Char16: + let attrData = AttributeInfo.Decode!(data); + args[argIdx] = scope:: box attrData; + case .Int32, + .UInt32, + .Char32: + let attrData = AttributeInfo.Decode!(data); + args[argIdx] = scope:: box attrData; + case .Float: + let attrData = AttributeInfo.Decode!(data); + args[argIdx] = scope:: box attrData; + case .Int64, + .UInt64, + .Double: + let attrData = AttributeInfo.Decode!(data); + args[argIdx] = scope:: box attrData; + case (TypeCode)typeof(TypeCode).MaxValue + 8: //BfConstType_TypeOf + let argTypeId = AttributeInfo.Decode!(data); + args[argIdx] = Type.[Friend]GetType((.)argTypeId); + case (TypeCode)255: + let stringId = AttributeInfo.Decode!(data); + String str = String.[Friend]sIdStringLiterals[stringId]; + args[argIdx] = str; + default: + Runtime.FatalError("Not handled"); + } + argIdx++; + } + + Type boxedAttrType = attrType.BoxedType; + + delete targetAttr; + targetAttr = boxedAttrType.CreateObject().Get(); + + if (methodInfo.Invoke((uint8*)Internal.UnsafeCastToPtr(targetAttr) + boxedAttrType.[Friend]mMemberDataOffset, params args) case .Ok(var val)) + val.Dispose(); + + attrIdx++; + return true; + } + + public void Dispose() + { + delete targetAttr; + } + + public Result GetNext() mut + { + if (!MoveNext()) + return .Err; + return Current; + } + } + + public struct CustomAttributeEnumerator : IEnumerator + { + void* data; + int32 attrIdx; + uint8 count; + T targetAttr; + + public this(void* inAttrData) + { + data = inAttrData; + data++; + attrIdx = 0; + count = data != null ? AttributeInfo.Decode!(data) : 0; + targetAttr = ?; + } + + public T Current + { + get + { + return targetAttr; + } + } + + public bool MoveNext() mut + { + if (attrIdx >= count || data == null) + return false; + + void* endPtr = null; + TypeId typeId = 0; + + while (true) + { + void* startPtr = data; + var len = AttributeInfo.Decode!(data); + endPtr = (uint8*)startPtr + len; + + typeId = AttributeInfo.Decode!(data); + if (typeId != typeof(T).TypeId) + { + attrIdx++; + if (attrIdx >= count) + return false; + data = endPtr; + continue; + } + + break; + } + + var methodIdx = AttributeInfo.Decode!(data); + + Type attrType = Type.[Friend]GetType(typeId); + TypeInstance attrTypeInst = attrType as TypeInstance; + MethodInfo methodInfo = .(attrTypeInst, attrTypeInst.[Friend]mMethodDataPtr + methodIdx); + + Object[] args = scope Object[methodInfo.[Friend]mData.mMethodData.mParamCount]; + + int argIdx = 0; + while (data < endPtr) + { + var attrDataType = AttributeInfo.Decode!(data); + switch (attrDataType) + { + case .Int8, + .UInt8, + .Char8, + .Boolean: + let attrData = AttributeInfo.Decode!(data); + args[argIdx] = scope:: box attrData; + case .Int16, + .UInt16, + .Char16: + let attrData = AttributeInfo.Decode!(data); + args[argIdx] = scope:: box attrData; + case .Int32, + .UInt32, + .Char32: + let attrData = AttributeInfo.Decode!(data); + args[argIdx] = scope:: box attrData; + case .Float: + let attrData = AttributeInfo.Decode!(data); + args[argIdx] = scope:: box attrData; + case .Int64, + .UInt64, + .Double: + let attrData = AttributeInfo.Decode!(data); + args[argIdx] = scope:: box attrData; + case (TypeCode)typeof(TypeCode).MaxValue + 8: //BfConstType_TypeOf + let argTypeId = AttributeInfo.Decode!(data); + args[argIdx] = Type.[Friend]GetType((.)argTypeId); + case (TypeCode)255: + let stringId = AttributeInfo.Decode!(data); + String str = String.[Friend]sIdStringLiterals[stringId]; + args[argIdx] = str; + default: + Runtime.FatalError("Not handled"); + } + argIdx++; + } + + if (methodInfo.Invoke(&targetAttr, params args) case .Ok(var val)) + val.Dispose(); + + attrIdx++; + return true; + } + + public void Dispose() + { + } + + public Result GetNext() mut + { + if (!MoveNext()) + return .Err; + return Current; + } + } } } diff --git a/BeefLibs/corlib/src/Reflection/FieldInfo.bf b/BeefLibs/corlib/src/Reflection/FieldInfo.bf index e656455e..30aa16c4 100644 --- a/BeefLibs/corlib/src/Reflection/FieldInfo.bf +++ b/BeefLibs/corlib/src/Reflection/FieldInfo.bf @@ -239,6 +239,20 @@ namespace System.Reflection return mTypeInstance.[Friend]GetCustomAttribute(mFieldData.mCustomAttributesIdx); } + public AttributeInfo.CustomAttributeEnumerator GetCustomAttributes() + { + if (Compiler.IsComptime) + Runtime.NotImplemented(); + return mTypeInstance.[Friend]GetCustomAttributes(mFieldData.mCustomAttributesIdx); + } + + public AttributeInfo.CustomAttributeEnumerator GetCustomAttributes() where T : Attribute + { + if (Compiler.IsComptime) + Runtime.NotImplemented(); + return mTypeInstance.[Friend]GetCustomAttributes(mFieldData.mCustomAttributesIdx); + } + void* GetDataPtrAndType(Object value, out Type type) { type = value.[Friend]RawGetType(); diff --git a/BeefLibs/corlib/src/Reflection/MethodInfo.bf b/BeefLibs/corlib/src/Reflection/MethodInfo.bf index 4524be83..d214a8a4 100644 --- a/BeefLibs/corlib/src/Reflection/MethodInfo.bf +++ b/BeefLibs/corlib/src/Reflection/MethodInfo.bf @@ -92,6 +92,22 @@ namespace System.Reflection return mTypeInstance.[Friend]GetCustomAttribute(mData.mMethodData.mParamData[paramIdx].mCustomAttributesIdx); } + public AttributeInfo.CustomAttributeEnumerator GetParamCustomAttributes(int paramIdx) + { + if (Compiler.IsComptime) + Runtime.NotImplemented(); + Debug.Assert((uint)paramIdx < (uint)mData.mMethodData.mParamCount); + return mTypeInstance.[Friend]GetCustomAttributes(mData.mMethodData.mParamData[paramIdx].mCustomAttributesIdx); + } + + public AttributeInfo.CustomAttributeEnumerator GetParamCustomAttributes(int paramIdx) where T : Attribute + { + if (Compiler.IsComptime) + Runtime.NotImplemented(); + Debug.Assert((uint)paramIdx < (uint)mData.mMethodData.mParamCount); + return mTypeInstance.[Friend]GetCustomAttributes(mData.mMethodData.mParamData[paramIdx].mCustomAttributesIdx); + } + public Result GetCustomAttribute() where T : Attribute { if (Compiler.IsComptime) @@ -104,6 +120,20 @@ namespace System.Reflection return mTypeInstance.[Friend]GetCustomAttribute(mData.mMethodData.mCustomAttributesIdx); } + public AttributeInfo.CustomAttributeEnumerator GetCustomAttributes() + { + if (Compiler.IsComptime) + Runtime.NotImplemented(); + return mTypeInstance.[Friend]GetCustomAttributes(mData.mMethodData.mCustomAttributesIdx); + } + + public AttributeInfo.CustomAttributeEnumerator GetCustomAttributes() where T : Attribute + { + if (Compiler.IsComptime) + Runtime.NotImplemented(); + return mTypeInstance.[Friend]GetCustomAttributes(mData.mMethodData.mCustomAttributesIdx); + } + public Result GetReturnCustomAttribute() where T : Attribute { if (Compiler.IsComptime) @@ -111,6 +141,20 @@ namespace System.Reflection return mTypeInstance.[Friend]GetCustomAttribute(mData.mMethodData.mReturnCustomAttributesIdx); } + public AttributeInfo.CustomAttributeEnumerator GetReturnCustomAttributes() + { + if (Compiler.IsComptime) + Runtime.NotImplemented(); + return mTypeInstance.[Friend]GetCustomAttributes(mData.mMethodData.mReturnCustomAttributesIdx); + } + + public AttributeInfo.CustomAttributeEnumerator GetReturnCustomAttributes() where T : Attribute + { + if (Compiler.IsComptime) + Runtime.NotImplemented(); + return mTypeInstance.[Friend]GetCustomAttributes(mData.mMethodData.mReturnCustomAttributesIdx); + } + public enum CallError { case None; diff --git a/BeefLibs/corlib/src/Type.bf b/BeefLibs/corlib/src/Type.bf index faafe812..f8db7ed5 100644 --- a/BeefLibs/corlib/src/Type.bf +++ b/BeefLibs/corlib/src/Type.bf @@ -670,6 +670,26 @@ namespace System return .Err; } + public AttributeInfo.CustomAttributeEnumerator GetCustomAttributes() + { + if (Compiler.IsComptime) + Runtime.NotImplemented(); + + if (var typeInstance = this as TypeInstance) + return typeInstance.[Friend]GetCustomAttributes(typeInstance.[Friend]mCustomAttributesIdx); + Runtime.NotImplemented(); + } + + public AttributeInfo.CustomAttributeEnumerator GetCustomAttributes() where T : Attribute + { + if (Compiler.IsComptime) + Runtime.NotImplemented(); + + if (var typeInstance = this as TypeInstance) + return typeInstance.[Friend]GetCustomAttributes(typeInstance.[Friend]mCustomAttributesIdx); + Runtime.NotImplemented(); + } + public override void ToString(String strBuffer) { GetFullName(strBuffer); @@ -1074,6 +1094,24 @@ namespace System.Reflection return .Err; } } + + AttributeInfo.CustomAttributeEnumerator GetCustomAttributes(int customAttributeIdx) + { + if (customAttributeIdx == -1) + return .(null); + + void* data = mCustomAttrDataPtr[customAttributeIdx]; + return .(data); + } + + AttributeInfo.CustomAttributeEnumerator GetCustomAttributes(int customAttributeIdx) where T : Attribute + { + if (customAttributeIdx == -1) + return .(null); + + void* data = mCustomAttrDataPtr[customAttributeIdx]; + return .(data); + } } [Ordered, AlwaysInclude(AssumeInstantiated=true)]