2020-04-29 06:40:03 -07:00
|
|
|
using System.Collections;
|
2019-08-23 11:56:54 -07:00
|
|
|
|
|
|
|
namespace System.Reflection
|
|
|
|
{
|
|
|
|
[CRepr, AlwaysInclude]
|
|
|
|
public struct FieldInfo
|
|
|
|
{
|
|
|
|
public enum Error
|
|
|
|
{
|
|
|
|
InvalidTargetType,
|
|
|
|
InvalidValueType
|
|
|
|
}
|
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
TypeInstance mTypeInstance;
|
|
|
|
TypeInstance.FieldData* mFieldData;
|
2019-08-23 11:56:54 -07:00
|
|
|
|
|
|
|
public this(TypeInstance typeInstance, TypeInstance.FieldData* fieldData)
|
|
|
|
{
|
|
|
|
mTypeInstance = typeInstance;
|
|
|
|
mFieldData = fieldData;
|
|
|
|
}
|
|
|
|
|
2021-10-25 10:29:04 -07:00
|
|
|
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;
|
2021-10-25 10:29:04 -07:00
|
|
|
public bool IsInstanceField => !mFieldData.mFlags.HasFlag(.Static) && !mFieldData.mFlags.HasFlag(.Const);
|
|
|
|
public StringView Name => mFieldData.mName;
|
2022-02-12 08:05:47 -05:00
|
|
|
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)
|
|
|
|
{
|
2020-03-09 06:34:16 -07:00
|
|
|
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");
|
|
|
|
}
|
2021-12-29 11:24:14 -05:00
|
|
|
dataAddr = (void*)((int)dataAddr + (.)mFieldData.mData);
|
2019-08-23 11:56:54 -07:00
|
|
|
|
2020-03-09 06:34:16 -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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
Type rawValueType = value.[Friend]RawGetType();
|
2020-06-23 07:32:53 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-09-05 06:02:13 -07:00
|
|
|
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)
|
|
|
|
{
|
2020-03-09 06:34:16 -07:00
|
|
|
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)
|
2020-09-05 06:02:13 -07:00
|
|
|
return .Err(.InvalidTargetType);
|
2019-08-23 11:56:54 -07:00
|
|
|
}
|
2021-12-29 11:24:14 -05:00
|
|
|
dataAddr = (void*)((int)dataAddr + (.)mFieldData.mData);
|
2019-08-23 11:56:54 -07:00
|
|
|
|
2020-03-09 06:34:16 -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
|
2020-09-05 06:02:13 -07:00
|
|
|
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*>();
|
|
|
|
}
|
2021-12-29 11:24:14 -05:00
|
|
|
dataAddr = (void*)((int)dataAddr + (.)mFieldData.mData);
|
2020-09-05 06:02:13 -07:00
|
|
|
|
|
|
|
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*>();
|
|
|
|
}
|
|
|
|
|
2021-12-29 11:24:14 -05:00
|
|
|
dataAddr = (void*)((int)dataAddr + (.)mFieldData.mData);
|
2020-09-05 06:02:13 -07:00
|
|
|
|
|
|
|
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)++)
|
|
|
|
}
|
|
|
|
|
2022-05-26 06:43:09 -07:00
|
|
|
public bool HasCustomAttribute<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))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
while (attrType != null);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return mTypeInstance.[Friend]HasCustomAttribute<T>(mFieldData.mCustomAttributesIdx);
|
|
|
|
}
|
|
|
|
|
2019-08-23 11:56:54 -07:00
|
|
|
public Result<T> GetCustomAttribute<T>() where T : Attribute
|
|
|
|
{
|
2022-02-17 05:51:05 -05:00
|
|
|
if (Compiler.IsComptime)
|
|
|
|
{
|
2022-02-26 22:31:32 -03:00
|
|
|
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);
|
2022-02-17 05:51:05 -05:00
|
|
|
return .Err;
|
|
|
|
}
|
2020-05-28 07:36:34 -07:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2022-02-26 22:31:32 -03:00
|
|
|
[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
|
|
|
}
|
|
|
|
|
2022-02-26 22:31:32 -03: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)
|
|
|
|
{
|
2020-03-09 06:34:16 -07:00
|
|
|
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;
|
2020-06-23 07:32:53 -07:00
|
|
|
return ((uint8*)Internal.UnsafeCastToPtr(value));
|
2019-08-23 11:56:54 -07:00
|
|
|
}
|
|
|
|
|
2020-09-05 06:02:13 -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
|
2020-09-05 06:02:13 -07:00
|
|
|
return .Err(.InvalidTargetType);
|
2020-07-06 09:55:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
|
2020-09-05 06:02:13 -07:00
|
|
|
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))
|
2020-09-05 06:02:13 -07:00
|
|
|
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
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
2019-08-23 11:56:54 -07:00
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
if (tMember.[Friend]mTypeCode == TypeCode.Object)
|
2019-08-23 11:56:54 -07:00
|
|
|
{
|
|
|
|
value = *(TMember*)targetDataAddr;
|
|
|
|
}
|
2020-03-09 06:34:16 -07:00
|
|
|
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
|
|
|
|
{
|
2020-09-05 06:02:13 -07:00
|
|
|
return .Err(.InvalidValueType);
|
2019-08-23 11:56:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return .Ok;
|
|
|
|
}
|
|
|
|
|
2020-09-05 06:02:13 -07:00
|
|
|
Result<Variant> GetValue(void* startTargetDataAddr, Type tTarget)
|
2019-08-23 11:56:54 -07:00
|
|
|
{
|
|
|
|
Variant value = Variant();
|
|
|
|
|
2020-09-05 06:02:13 -07:00
|
|
|
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
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
2019-08-23 11:56:54 -07:00
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
TypeCode typeCode = fieldType.[Friend]mTypeCode;
|
2019-08-23 11:56:54 -07:00
|
|
|
if (typeCode == TypeCode.Enum)
|
2020-03-09 06:34:16 -07:00
|
|
|
typeCode = fieldType.UnderlyingType.[Friend]mTypeCode;
|
2019-08-23 11:56:54 -07:00
|
|
|
|
2020-09-05 06:02:13 -07:00
|
|
|
if (typeCode == TypeCode.Object)
|
|
|
|
{
|
2020-03-09 06:34:16 -07:00
|
|
|
value.[Friend]mStructType = 0;
|
2020-09-05 06:02:13 -07:00
|
|
|
value.[Friend]mData = *(int*)targetDataAddr;
|
|
|
|
}
|
2019-08-23 11:56:54 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
value = Variant.Create(fieldType, targetDataAddr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2020-09-05 06:02:13 -07:00
|
|
|
public Result<Variant> GetValueReference(void* startTargetDataAddr, Type tTarget)
|
2020-07-06 09:09:28 -07:00
|
|
|
{
|
|
|
|
Variant value = Variant();
|
|
|
|
|
2020-09-05 06:02:13 -07:00
|
|
|
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
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
2019-08-23 11:56:54 -07:00
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
TypeCode typeCode = fieldType.[Friend]mTypeCode;
|
2019-08-23 11:56:54 -07:00
|
|
|
if (typeCode == TypeCode.Enum)
|
2020-03-09 06:34:16 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-09-05 06:02:13 -07:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
public struct Enumerator : IEnumerator<FieldInfo>
|
2019-08-23 11:56:54 -07:00
|
|
|
{
|
|
|
|
BindingFlags mBindingFlags;
|
|
|
|
TypeInstance mTypeInstance;
|
|
|
|
int32 mIdx;
|
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
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++;
|
2020-03-09 06:34:16 -07:00
|
|
|
if (mIdx == mTypeInstance.[Friend]mFieldDataCount)
|
2021-10-25 10:29:04 -07:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2020-03-09 06:34:16 -07:00
|
|
|
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
|
|
|
|
{
|
2020-03-09 06:34:16 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|