1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00
Beef/BeefLibs/corlib/src/Reflection/FieldInfo.bf

577 lines
15 KiB
Beef
Raw Normal View History

using System.Collections;
2019-08-23 11:56:54 -07:00
namespace System.Reflection
{
[CRepr, AlwaysInclude]
public struct FieldInfo
{
public enum Error
{
InvalidTargetType,
InvalidValueType
}
TypeInstance mTypeInstance;
TypeInstance.FieldData* mFieldData;
2019-08-23 11:56:54 -07:00
public this(TypeInstance typeInstance, TypeInstance.FieldData* fieldData)
{
mTypeInstance = typeInstance;
mFieldData = fieldData;
}
public TypeInstance DeclaringType => mTypeInstance;
public int32 MemberOffset => (int32)mFieldData.mData;
public Type FieldType => Type.[Friend]GetType(mFieldData.mFieldTypeId);
public bool IsConst => mFieldData.mFlags.HasFlag(.Const);
public bool IsStatic => mFieldData.mFlags.HasFlag(.Static);
2022-03-16 15:40:27 -07:00
public bool IsPublic => (mFieldData.mFlags & .FieldAccessMask) == .Public;
public bool IsProtected => (mFieldData.mFlags & .FieldAccessMask) == .Protected;
public bool IsPrivate => (mFieldData.mFlags & .FieldAccessMask) == 0;
public bool IsInstanceField => !mFieldData.mFlags.HasFlag(.Static) && !mFieldData.mFlags.HasFlag(.Const);
public StringView Name => mFieldData.mName;
public int32 FieldIdx => Compiler.IsComptime ?
mFieldData.mCustomAttributesIdx :
-1;
2019-08-23 11:56:54 -07:00
public Result<void, Error> SetValue(Object obj, Object value)
{
2020-08-25 07:08:44 -07:00
void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj));
2019-08-23 11:56:54 -07:00
if (mTypeInstance.IsStruct)
{
Type boxedType = obj.[Friend]RawGetType();
2019-08-23 11:56:54 -07:00
bool typeMatched = false;
if (boxedType.IsBoxed)
2020-08-25 07:08:44 -07:00
{
if (mTypeInstance == boxedType.UnderlyingType)
{
dataAddr = (void*)((int)dataAddr + boxedType.[Friend]mMemberDataOffset);
if (boxedType.IsBoxedStructPtr)
dataAddr = *(void**)dataAddr;
typeMatched = true;
}
}
2019-08-23 11:56:54 -07:00
if (!typeMatched)
return .Err(.InvalidTargetType); // "Invalid target type");
}
dataAddr = (void*)((int)dataAddr + (.)mFieldData.mData);
2019-08-23 11:56:54 -07:00
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
2019-11-29 09:24:13 -08:00
2020-06-25 05:38:42 -07:00
if (value == null)
{
if ((fieldType.IsValueType) && (!fieldType.IsPointer))
{
return .Err(.InvalidValueType);
}
else
{
2020-08-25 07:08:44 -07:00
*((int*)dataAddr) = 0;
2020-06-25 05:38:42 -07:00
return .Ok;
}
}
Type rawValueType = value.[Friend]RawGetType();
void* valueDataAddr = ((uint8*)Internal.UnsafeCastToPtr(value)) + rawValueType.[Friend]mMemberDataOffset;
2020-08-25 07:08:44 -07:00
if (rawValueType.IsBoxedStructPtr)
valueDataAddr = *(void**)valueDataAddr;
2019-11-29 09:24:13 -08:00
Type valueType = value.GetType();
if ((valueType != fieldType) && (valueType.IsTypedPrimitive))
valueType = valueType.UnderlyingType;
if (valueType == fieldType)
{
2020-05-13 15:07:03 -07:00
if (valueType.IsObject)
2020-08-25 07:08:44 -07:00
*((void**)dataAddr) = Internal.UnsafeCastToPtr(value);
2020-05-13 15:07:03 -07:00
else
2020-08-25 07:08:44 -07:00
Internal.MemCpy(dataAddr, valueDataAddr, fieldType.[Friend]mSize);
2019-11-29 09:24:13 -08:00
}
else
{
return .Err(.InvalidValueType);
}
2019-08-23 11:56:54 -07:00
return .Ok;
}
public Result<void, Error> SetValue(Object obj, Variant value)
2019-08-23 11:56:54 -07:00
{
2020-08-25 07:08:44 -07:00
void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj));
2019-08-23 11:56:54 -07:00
if (mTypeInstance.IsStruct)
{
Type boxedType = obj.[Friend]RawGetType();
2019-08-23 11:56:54 -07:00
bool typeMatched = false;
if (boxedType.IsBoxed)
{
if (mTypeInstance == boxedType.UnderlyingType)
{
2020-08-25 07:08:44 -07:00
dataAddr = (void*)((int)dataAddr + boxedType.[Friend]mMemberDataOffset);
if (boxedType.IsBoxedStructPtr)
dataAddr = *(void**)dataAddr;
2019-08-23 11:56:54 -07:00
typeMatched = true;
}
}
if (!typeMatched)
return .Err(.InvalidTargetType);
2019-08-23 11:56:54 -07:00
}
dataAddr = (void*)((int)dataAddr + (.)mFieldData.mData);
2019-08-23 11:56:54 -07:00
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
2019-08-23 11:56:54 -07:00
2020-08-25 07:08:44 -07:00
let variantType = value.VariantType;
if (variantType != fieldType)
{
if ((variantType.IsPointer) && (variantType.UnderlyingType == fieldType))
{
void* srcPtr = value.Get<void*>();
Internal.MemCpy(dataAddr, srcPtr, fieldType.Size);
return .Ok;
}
else
return .Err(.InvalidValueType);
}
value.CopyValueData(dataAddr);
return .Ok;
}
public Result<void, Error> SetValue(Variant target, Object value)
{
var target;
var targetType = target.VariantType;
void* dataAddr = target.DataPtr;
if (targetType != mTypeInstance)
{
if ((!targetType.IsPointer) || (targetType.UnderlyingType.IsSubtypeOf(mTypeInstance)))
return .Err(.InvalidTargetType); // Invalid target type
dataAddr = target.Get<void*>();
}
dataAddr = (void*)((int)dataAddr + (.)mFieldData.mData);
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
if (value == null)
{
if ((fieldType.IsValueType) && (!fieldType.IsPointer))
{
return .Err(.InvalidValueType);
}
else
{
*((int*)dataAddr) = 0;
return .Ok;
}
}
Type rawValueType = value.[Friend]RawGetType();
void* valueDataAddr = ((uint8*)Internal.UnsafeCastToPtr(value)) + rawValueType.[Friend]mMemberDataOffset;
if (rawValueType.IsBoxedStructPtr)
valueDataAddr = *(void**)valueDataAddr;
Type valueType = value.GetType();
if ((valueType != fieldType) && (valueType.IsTypedPrimitive))
valueType = valueType.UnderlyingType;
if (valueType == fieldType)
{
if (valueType.IsObject)
*((void**)dataAddr) = Internal.UnsafeCastToPtr(value);
else
Internal.MemCpy(dataAddr, valueDataAddr, fieldType.[Friend]mSize);
}
else
{
return .Err(.InvalidValueType);
}
return .Ok;
}
public Result<void, Error> SetValue(Variant target, Variant value)
{
var target;
var targetType = target.VariantType;
void* dataAddr = target.DataPtr;
if (targetType != mTypeInstance)
{
if ((!targetType.IsPointer) || (targetType.UnderlyingType.IsSubtypeOf(mTypeInstance)))
return .Err(.InvalidTargetType);
dataAddr = target.Get<void*>();
}
dataAddr = (void*)((int)dataAddr + (.)mFieldData.mData);
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
let variantType = value.VariantType;
if (variantType != fieldType)
{
if ((variantType.IsPointer) && (variantType.UnderlyingType == fieldType))
{
void* srcPtr = value.Get<void*>();
Internal.MemCpy(dataAddr, srcPtr, fieldType.Size);
return .Ok;
}
else
return .Err(.InvalidValueType);
2020-08-25 07:08:44 -07:00
}
2019-08-23 11:56:54 -07:00
value.CopyValueData(dataAddr);
return .Ok;
}
static mixin Decode<T2>(void* data)
{
*((*(T2**)&data)++)
}
public Result<T> GetCustomAttribute<T>() where T : Attribute
{
if (Compiler.IsComptime)
{
int32 attrIdx = -1;
Type attrType = null;
repeat
{
attrType = Type.[Friend]Comptime_Field_GetCustomAttributeType((int32)mTypeInstance.TypeId, mFieldData.mCustomAttributesIdx, ++attrIdx);
if (attrType == typeof(T))
{
T val = ?;
if (Type.[Friend]Comptime_Field_GetCustomAttribute((int32)mTypeInstance.TypeId, mFieldData.mCustomAttributesIdx, attrIdx, &val))
return val;
}
}
while (attrType != null);
return .Err;
}
return mTypeInstance.[Friend]GetCustomAttribute<T>(mFieldData.mCustomAttributesIdx);
2022-02-26 13:43:56 -03:00
}
public AttributeInfo.CustomAttributeEnumerator GetCustomAttributes()
{
return mTypeInstance.[Friend]GetCustomAttributes(mFieldData.mCustomAttributesIdx);
}
[Comptime]
public AttributeInfo.ComptimeFieldCustomAttributeEnumerator GetCustomAttributes()
{
return .((int32)mTypeInstance.TypeId, mFieldData.mCustomAttributesIdx);
}
2022-02-26 13:43:56 -03:00
public AttributeInfo.CustomAttributeEnumerator<T> GetCustomAttributes<T>() where T : Attribute
{
return mTypeInstance.[Friend]GetCustomAttributes<T>(mFieldData.mCustomAttributesIdx);
2019-08-23 11:56:54 -07:00
}
[Comptime]
public AttributeInfo.ComptimeFieldCustomAttributeEnumerator<T> GetCustomAttributes<T>() where T : Attribute
{
return .((int32)mTypeInstance.TypeId, mFieldData.mCustomAttributesIdx);
}
2019-08-23 11:56:54 -07:00
void* GetDataPtrAndType(Object value, out Type type)
{
type = value.[Friend]RawGetType();
2020-08-25 07:08:44 -07:00
if (type.IsBoxedStructPtr)
return *(void**)(((uint8*)Internal.UnsafeCastToPtr(value)) + type.[Friend]mMemberDataOffset);
2019-08-23 11:56:54 -07:00
if (type.IsBoxed)
2020-08-24 10:19:17 -07:00
return ((uint8*)Internal.UnsafeCastToPtr(value)) + type.[Friend]mMemberDataOffset;
return ((uint8*)Internal.UnsafeCastToPtr(value));
2019-08-23 11:56:54 -07:00
}
public Result<void, Error> GetValue<TMember>(Object target, out TMember value)
2019-08-23 11:56:54 -07:00
{
value = default(TMember);
2020-07-06 09:55:19 -07:00
void* targetDataAddr;
if (target == null)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
// Unhandled
return .Err(.InvalidTargetType);
2020-07-06 09:55:19 -07:00
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err(.InvalidTargetType);
2020-07-06 09:55:19 -07:00
targetDataAddr = null;
}
else
{
Type tTarget;
targetDataAddr = GetDataPtrAndType(target, out tTarget);
if (!tTarget.IsSubtypeOf(mTypeInstance))
return .Err(.InvalidTargetType); //"Invalid type");
2020-07-06 09:55:19 -07:00
}
2019-11-29 09:24:13 -08:00
2019-08-23 11:56:54 -07:00
Type tMember = typeof(TMember);
2020-07-06 09:55:19 -07:00
targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData;
2019-08-23 11:56:54 -07:00
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
2019-08-23 11:56:54 -07:00
if (tMember.[Friend]mTypeCode == TypeCode.Object)
2019-08-23 11:56:54 -07:00
{
value = *(TMember*)targetDataAddr;
}
else if (fieldType.[Friend]mTypeCode == tMember.[Friend]mTypeCode)
2019-11-29 09:24:13 -08:00
{
Internal.MemCpy(&value, targetDataAddr, tMember.Size);
}
2019-08-23 11:56:54 -07:00
else
{
return .Err(.InvalidValueType);
2019-08-23 11:56:54 -07:00
}
return .Ok;
}
Result<Variant> GetValue(void* startTargetDataAddr, Type tTarget)
2019-08-23 11:56:54 -07:00
{
Variant value = Variant();
void* targetDataAddr = startTargetDataAddr;
if (targetDataAddr == null)
2020-07-06 09:55:19 -07:00
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return Variant.Create(FieldType, &mFieldData.mData);
}
2019-08-23 11:56:54 -07:00
2020-07-06 09:55:19 -07:00
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
}
else
{
if (!tTarget.IsSubtypeOf(mTypeInstance))
return .Err; //Invalid type;
}
targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData;
2019-08-23 11:56:54 -07:00
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
2019-08-23 11:56:54 -07:00
TypeCode typeCode = fieldType.[Friend]mTypeCode;
2019-08-23 11:56:54 -07:00
if (typeCode == TypeCode.Enum)
typeCode = fieldType.UnderlyingType.[Friend]mTypeCode;
2019-08-23 11:56:54 -07:00
if (typeCode == TypeCode.Object)
{
value.[Friend]mStructType = 0;
value.[Friend]mData = *(int*)targetDataAddr;
}
2019-08-23 11:56:54 -07:00
else
{
value = Variant.Create(fieldType, targetDataAddr);
}
return value;
}
public Result<Variant> GetValueReference(void* startTargetDataAddr, Type tTarget)
{
Variant value = Variant();
void* targetDataAddr = startTargetDataAddr;
if (targetDataAddr == null)
2020-07-06 09:55:19 -07:00
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return Variant.Create(FieldType, &mFieldData.mData);
}
2019-08-23 11:56:54 -07:00
2020-07-06 09:55:19 -07:00
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
2019-08-23 11:56:54 -07:00
2020-07-06 09:55:19 -07:00
targetDataAddr = null;
2019-08-23 11:56:54 -07:00
}
2020-07-06 09:55:19 -07:00
else
{
if (!tTarget.IsSubtypeOf(mTypeInstance))
return .Err; //Invalid type;
}
2019-08-23 11:56:54 -07:00
2020-07-06 09:55:19 -07:00
targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData;
2019-08-23 11:56:54 -07:00
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
2019-08-23 11:56:54 -07:00
TypeCode typeCode = fieldType.[Friend]mTypeCode;
2019-08-23 11:56:54 -07:00
if (typeCode == TypeCode.Enum)
typeCode = fieldType.UnderlyingType.[Friend]mTypeCode;
2020-07-06 09:55:19 -07:00
value = Variant.CreateReference(fieldType, targetDataAddr);
2019-08-23 11:56:54 -07:00
return value;
}
public Result<Variant> GetValue(Object target)
{
void* targetDataAddr;
if (target == null)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return Variant.Create(FieldType, &mFieldData.mData);
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
return GetValue(null, null);
}
else
{
Type tTarget;
targetDataAddr = GetDataPtrAndType(target, out tTarget);
return GetValue(targetDataAddr, tTarget);
}
}
public Result<Variant> GetValue(Variant target)
{
if (!target.HasValue)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return Variant.Create(FieldType, &mFieldData.mData);
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
return GetValue(null, null);
}
else
{
var target;
return GetValue(target.DataPtr, target.VariantType);
}
}
public Result<Variant> GetValueReference(Object target)
{
void* targetDataAddr;
if (target == null)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return Variant.Create(FieldType, &mFieldData.mData);
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
return GetValueReference(null, null);
}
else
{
Type tTarget;
targetDataAddr = GetDataPtrAndType(target, out tTarget);
return GetValueReference(targetDataAddr, tTarget);
}
}
public Result<Variant> GetValueReference(Variant target)
{
if (!target.HasValue)
{
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
{
return Variant.Create(FieldType, &mFieldData.mData);
}
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
return .Err;
return GetValueReference(null, null);
}
else
{
var target;
return GetValueReference(target.DataPtr, target.VariantType);
}
}
public struct Enumerator : IEnumerator<FieldInfo>
2019-08-23 11:56:54 -07:00
{
BindingFlags mBindingFlags;
TypeInstance mTypeInstance;
int32 mIdx;
public this(TypeInstance typeInst, BindingFlags bindingFlags)
2019-08-23 11:56:54 -07:00
{
mTypeInstance = typeInst;
mBindingFlags = bindingFlags;
mIdx = -1;
}
public void Reset() mut
{
mIdx = -1;
}
public void Dispose()
{
}
public bool MoveNext() mut
{
if (mTypeInstance == null)
return false;
for (;;)
{
mIdx++;
if (mIdx == mTypeInstance.[Friend]mFieldDataCount)
{
if (mBindingFlags.HasFlag(.DeclaredOnly))
return false;
if (mTypeInstance.[Friend]mBaseType == 0)
return false;
mTypeInstance = Type.[Friend]GetType(mTypeInstance.[Friend]mBaseType) as TypeInstance;
mIdx = -1;
continue;
}
var fieldData = &mTypeInstance.[Friend]mFieldDataPtr[mIdx];
2019-08-23 11:56:54 -07:00
bool matches = (mBindingFlags.HasFlag(BindingFlags.Static) && (fieldData.mFlags.HasFlag(FieldFlags.Static)));
matches |= (mBindingFlags.HasFlag(BindingFlags.Instance) && (!fieldData.mFlags.HasFlag(FieldFlags.Static)));
if (matches)
break;
}
return true;
}
public FieldInfo Current
{
get
{
var fieldData = &mTypeInstance.[Friend]mFieldDataPtr[mIdx];
2019-08-23 11:56:54 -07:00
return FieldInfo(mTypeInstance, fieldData);
}
}
2020-12-23 08:53:38 -08:00
public int32 Index
{
get
{
return mIdx;
}
}
2019-08-23 11:56:54 -07:00
public Result<FieldInfo> GetNext() mut
{
if (!MoveNext())
return .Err;
return Current;
}
}
}
}