using System.Collections; namespace System.Reflection { class AttributeInfo { static mixin Decode(void* data) { *((*(T2**)&data)++) } public static bool HasCustomAttribute(void* inAttrData, Type attributeType) { TypeId findTypeId = attributeType.[Friend]mTypeId; void* data = inAttrData; data++; uint8 count = Decode!(data); for (int32 attrIdx = 0; attrIdx < count; attrIdx++) AttrBlock: { void* startPtr = data; var len = Decode!(data); void* endPtr = (uint8*)startPtr + len; var typeId = Decode!(data); if (typeId == findTypeId) return true; data = endPtr; } return false; } public static Result GetCustomAttribute(void* inAttrData, Type attributeType, Object targetAttr) { TypeId findTypeId = attributeType.[Friend]mTypeId; void* data = inAttrData; data++; uint8 count = Decode!(data); for (int32 attrIdx = 0; attrIdx < count; attrIdx++) AttrBlock: { void* startPtr = data; var len = Decode!(data); void* endPtr = (uint8*)startPtr + len; var typeId = Decode!(data); if (typeId != findTypeId) { data = endPtr; continue; } var methodIdx = 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 = Decode!(data); switch (attrDataType) { case .Int8, .UInt8, .Char8, .Boolean: let attrData = Decode!(data); args[argIdx] = scope:AttrBlock box attrData; case .Int16, .UInt16, .Char16: let attrData = Decode!(data); args[argIdx] = scope:AttrBlock box attrData; case .Int32, .UInt32, .Char32: let attrData = Decode!(data); args[argIdx] = scope:AttrBlock box attrData; case .Float: let attrData = Decode!(data); args[argIdx] = scope:AttrBlock box attrData; case .Int64, .UInt64, .Double: let attrData = Decode!(data); args[argIdx] = scope:AttrBlock box attrData; case (TypeCode)typeof(TypeCode).MaxValue + 8: //BfConstType_TypeOf let argTypeId = Decode!(data); args[argIdx] = Type.[Friend]GetType((.)argTypeId); case (TypeCode)255: let stringId = 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(); else return .Err; return .Ok; } return .Err; } public struct CustomAttributeEnumerator : IEnumerator, IDisposable { void* mData; int32 mAttrIdx; uint8 mCount; Variant mTargetAttr; public this(void* inAttrData) { mData = inAttrData; mData++; mAttrIdx = 0; mCount = mData != null ? AttributeInfo.Decode!(mData) : 0; mTargetAttr = default; } public Variant Current { get { return mTargetAttr; } } public bool MoveNext() mut { if (mAttrIdx >= mCount || mData == null) return false; void* startPtr = mData; var len = AttributeInfo.Decode!(mData); void* endPtr = (uint8*)startPtr + len; var typeId = AttributeInfo.Decode!(mData); var methodIdx = AttributeInfo.Decode!(mData); 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 (mData < endPtr) { var attrDataType = AttributeInfo.Decode!(mData); switch (attrDataType) { case .Int8, .UInt8, .Char8, .Boolean: let attrData = AttributeInfo.Decode!(mData); args[argIdx] = scope:: box attrData; case .Int16, .UInt16, .Char16: let attrData = AttributeInfo.Decode!(mData); args[argIdx] = scope:: box attrData; case .Int32, .UInt32, .Char32: let attrData = AttributeInfo.Decode!(mData); args[argIdx] = scope:: box attrData; case .Float: let attrData = AttributeInfo.Decode!(mData); args[argIdx] = scope:: box attrData; case .Int64, .UInt64, .Double: let attrData = AttributeInfo.Decode!(mData); args[argIdx] = scope:: box attrData; case (TypeCode)typeof(TypeCode).MaxValue + 8: //BfConstType_TypeOf let argTypeId = AttributeInfo.Decode!(mData); args[argIdx] = Type.[Friend]GetType((.)argTypeId); case (TypeCode)255: let stringId = AttributeInfo.Decode!(mData); String str = String.[Friend]sIdStringLiterals[stringId]; args[argIdx] = str; default: Runtime.FatalError("Not handled"); } argIdx++; } mTargetAttr.Dispose(); void* data = Variant.Alloc(attrType, out mTargetAttr); if (methodInfo.Invoke(data, params args) case .Ok(var val)) val.Dispose(); mAttrIdx++; return true; } public void Dispose() mut { mTargetAttr.Dispose(); } public Result GetNext() mut { if (!MoveNext()) return .Err; return Current; } } public struct ComptimeTypeCustomAttributeEnumerator : IEnumerator, IDisposable { int32 mTypeId; int32 mAttrIdx; Variant mTargetAttr; public this(int32 typeId) { mTypeId = typeId; mAttrIdx = -1; mTargetAttr = default; } public Variant Current { get { return mTargetAttr; } } public bool MoveNext() mut { let attrType = Type.[Friend]Comptime_Type_GetCustomAttributeType(mTypeId, ++mAttrIdx); if (attrType != null) { mTargetAttr.Dispose(); void* data = Variant.Alloc(attrType, out mTargetAttr); if (Type.[Friend]Comptime_Type_GetCustomAttribute(mTypeId, mAttrIdx, data)) return true; } return false; } public void Dispose() mut { mTargetAttr.Dispose(); } public Result GetNext() mut { if (!MoveNext()) return .Err; return Current; } } public struct ComptimeFieldCustomAttributeEnumerator : IEnumerator, IDisposable { int32 mTypeId; int32 mFieldIdx; int32 mAttrIdx; Variant mTargetAttr; public this(int32 typeId, int32 fieldIdx) { mTypeId = typeId; mFieldIdx = fieldIdx; mAttrIdx = -1; mTargetAttr = default; } public Variant Current { get { return mTargetAttr; } } public bool MoveNext() mut { let attrType = Type.[Friend]Comptime_Field_GetCustomAttributeType(mTypeId, mFieldIdx, ++mAttrIdx); if (attrType != null) { mTargetAttr.Dispose(); void* data = Variant.Alloc(attrType, out mTargetAttr); if (Type.[Friend]Comptime_Field_GetCustomAttribute(mTypeId, mFieldIdx, mAttrIdx, data)) return true; } return false; } public void Dispose() mut { mTargetAttr.Dispose(); } public Result GetNext() mut { if (!MoveNext()) return .Err; return Current; } } public struct ComptimeMethodCustomAttributeEnumerator : IEnumerator, IDisposable { int64 mMethodHandle; int32 mAttrIdx; Variant mTargetAttr; public this(int64 methodHandle) { mMethodHandle = methodHandle; mAttrIdx = -1; mTargetAttr = default; } public Variant Current { get { return mTargetAttr; } } public bool MoveNext() mut { let attrType = Type.[Friend]Comptime_Method_GetCustomAttributeType(mMethodHandle, ++mAttrIdx); if (attrType != null) { mTargetAttr.Dispose(); void* data = Variant.Alloc(attrType, out mTargetAttr); if (Type.[Friend]Comptime_Method_GetCustomAttribute(mMethodHandle, mAttrIdx, data)) return true; } return false; } public void Dispose() mut { mTargetAttr.Dispose(); } public Result GetNext() mut { if (!MoveNext()) return .Err; return Current; } } public struct CustomAttributeEnumerator : IEnumerator { void* mData; int32 mAttrIdx; uint8 mCount; T mTargetAttr; public this(void* inAttrData) { mData = inAttrData; mData++; mAttrIdx = 0; mCount = mData != null ? AttributeInfo.Decode!(mData) : 0; mTargetAttr = ?; } public T Current { get { return mTargetAttr; } } public bool MoveNext() mut { if (mAttrIdx >= mCount || mData == null) return false; void* endPtr = null; TypeId typeId = 0; while (true) { void* startPtr = mData; var len = AttributeInfo.Decode!(mData); endPtr = (uint8*)startPtr + len; typeId = AttributeInfo.Decode!(mData); if (typeId != typeof(T).TypeId) { mAttrIdx++; if (mAttrIdx >= mCount) return false; mData = endPtr; continue; } break; } var methodIdx = AttributeInfo.Decode!(mData); 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 (mData < endPtr) { var attrDataType = AttributeInfo.Decode!(mData); switch (attrDataType) { case .Int8, .UInt8, .Char8, .Boolean: let attrData = AttributeInfo.Decode!(mData); args[argIdx] = scope:: box attrData; case .Int16, .UInt16, .Char16: let attrData = AttributeInfo.Decode!(mData); args[argIdx] = scope:: box attrData; case .Int32, .UInt32, .Char32: let attrData = AttributeInfo.Decode!(mData); args[argIdx] = scope:: box attrData; case .Float: let attrData = AttributeInfo.Decode!(mData); args[argIdx] = scope:: box attrData; case .Int64, .UInt64, .Double: let attrData = AttributeInfo.Decode!(mData); args[argIdx] = scope:: box attrData; case (TypeCode)typeof(TypeCode).MaxValue + 8: //BfConstType_TypeOf let argTypeId = AttributeInfo.Decode!(mData); args[argIdx] = Type.[Friend]GetType((.)argTypeId); case (TypeCode)255: let stringId = AttributeInfo.Decode!(mData); String str = String.[Friend]sIdStringLiterals[stringId]; args[argIdx] = str; default: Runtime.FatalError("Not handled"); } argIdx++; } if (methodInfo.Invoke(&mTargetAttr, params args) case .Ok(var val)) val.Dispose(); mAttrIdx++; return true; } public void Dispose() { } public Result GetNext() mut { if (!MoveNext()) return .Err; return Current; } } public struct ComptimeTypeCustomAttributeEnumerator : IEnumerator { int32 mTypeId; int32 mAttrIdx; T mTargetAttr; public this(int32 typeId) { mTypeId = typeId; mAttrIdx = -1; mTargetAttr = ?; } public T Current { get { return mTargetAttr; } } public bool MoveNext() mut { Type attrType = null; repeat { attrType = Type.[Friend]Comptime_Type_GetCustomAttributeType(mTypeId, ++mAttrIdx); if (attrType == typeof(T)) { if (Type.[Friend]Comptime_Type_GetCustomAttribute(mTypeId, mAttrIdx, &mTargetAttr)) return true; } } while (attrType != null); return false; } public void Dispose() { } public Result GetNext() mut { if (!MoveNext()) return .Err; return Current; } } public struct ComptimeFieldCustomAttributeEnumerator : IEnumerator { int32 mTypeId; int32 mFieldIdx; int32 mAttrIdx; T mTargetAttr; public this(int32 typeId, int32 fieldIdx) { mTypeId = typeId; mFieldIdx = fieldIdx; mAttrIdx = -1; mTargetAttr = ?; } public T Current { get { return mTargetAttr; } } public bool MoveNext() mut { Type attrType = null; repeat { attrType = Type.[Friend]Comptime_Field_GetCustomAttributeType(mTypeId, mFieldIdx, ++mAttrIdx); if (attrType == typeof(T)) { if (Type.[Friend]Comptime_Field_GetCustomAttribute(mTypeId, mFieldIdx, mAttrIdx, &mTargetAttr)) return true; } } while (attrType != null); return false; } public void Dispose() { } public Result GetNext() mut { if (!MoveNext()) return .Err; return Current; } } public struct ComptimeMethodCustomAttributeEnumerator : IEnumerator { int64 mMethodHandle; int32 mAttrIdx; T mTargetAttr; public this(int64 methodHandle) { mMethodHandle = methodHandle; mAttrIdx = -1; mTargetAttr = ?; } public T Current { get { return mTargetAttr; } } public bool MoveNext() mut { Type attrType = null; repeat { attrType = Type.[Friend]Comptime_Method_GetCustomAttributeType(mMethodHandle, ++mAttrIdx); if (attrType == typeof(T)) { if (Type.[Friend]Comptime_Method_GetCustomAttribute(mMethodHandle, mAttrIdx, &mTargetAttr)) return true; } } while (attrType != null); return false; } public void Dispose() { } public Result GetNext() mut { if (!MoveNext()) return .Err; return Current; } } } }