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;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int32 MemberOffset
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return mFieldData.mDataOffset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Type FieldType
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2020-03-09 06:34:16 -07:00
|
|
|
return Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
2019-08-23 11:56:54 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public StringView Name
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return mFieldData.mName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Result<void, Error> SetValue(Object obj, Object value)
|
|
|
|
{
|
|
|
|
int32 dataOffsetAdjust = 0;
|
|
|
|
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-03-09 06:34:16 -07:00
|
|
|
dataOffsetAdjust = boxedType.[Friend]mMemberDataOffset;
|
2019-08-23 11:56:54 -07:00
|
|
|
typeMatched = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!typeMatched)
|
|
|
|
return .Err(.InvalidTargetType); // "Invalid target type");
|
|
|
|
}
|
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
2020-06-23 07:32:53 -07:00
|
|
|
void* fieldDataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj)) + mFieldData.mDataOffset + dataOffsetAdjust;
|
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
|
|
|
|
{
|
|
|
|
*((int*)fieldDataAddr) = 0;
|
|
|
|
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;
|
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)
|
|
|
|
*((void**)fieldDataAddr) = Internal.UnsafeCastToPtr(value);
|
|
|
|
else
|
|
|
|
Internal.MemCpy(fieldDataAddr, 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> SetValue(Object obj, Variant value)
|
|
|
|
{
|
|
|
|
int32 dataOffsetAdjust = 0;
|
|
|
|
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-03-09 06:34:16 -07:00
|
|
|
dataOffsetAdjust = boxedType.[Friend]mMemberDataOffset;
|
2019-08-23 11:56:54 -07:00
|
|
|
typeMatched = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!typeMatched)
|
|
|
|
return .Err;//("Invalid target type");
|
|
|
|
}
|
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
2019-08-23 11:56:54 -07:00
|
|
|
|
2020-06-23 07:32:53 -07:00
|
|
|
void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj)) + mFieldData.mDataOffset + dataOffsetAdjust;
|
2019-08-23 11:56:54 -07:00
|
|
|
|
|
|
|
if (value.VariantType != fieldType)
|
|
|
|
return .Err;//("Invalid type");
|
|
|
|
|
|
|
|
value.CopyValueData(dataAddr);
|
|
|
|
|
|
|
|
return .Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
static mixin Decode<T2>(void* data)
|
|
|
|
{
|
|
|
|
*((*(T2**)&data)++)
|
|
|
|
}
|
|
|
|
|
|
|
|
public Result<T> GetCustomAttribute<T>() where T : Attribute
|
|
|
|
{
|
2020-05-28 07:36:34 -07:00
|
|
|
return mTypeInstance.[Friend]GetCustomAttribute<T>(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();
|
2019-08-23 11:56:54 -07:00
|
|
|
/*if (type.IsStruct)
|
|
|
|
return &value;*/
|
|
|
|
|
|
|
|
if (type.IsBoxed)
|
2020-03-09 06:34:16 -07:00
|
|
|
return ((uint8*)(void*)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
|
|
|
}
|
|
|
|
|
|
|
|
public Result<void> GetValue<TMember>(Object target, out TMember value)
|
|
|
|
{
|
|
|
|
value = default(TMember);
|
|
|
|
|
|
|
|
Type tTarget;
|
|
|
|
void* targetDataAddr = GetDataPtrAndType(target, out tTarget);
|
2019-11-29 09:24:13 -08:00
|
|
|
|
2019-08-23 11:56:54 -07:00
|
|
|
Type tMember = typeof(TMember);
|
|
|
|
|
|
|
|
targetDataAddr = (uint8*)targetDataAddr + mFieldData.mDataOffset;
|
|
|
|
|
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
|
|
|
{
|
|
|
|
if (!tTarget.IsSubtypeOf(mTypeInstance))
|
|
|
|
Runtime.FatalError();
|
|
|
|
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
|
|
|
|
{
|
2019-11-29 09:24:13 -08:00
|
|
|
return .Err;
|
2019-08-23 11:56:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return .Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Result<Variant> GetValue(Object target)
|
|
|
|
{
|
|
|
|
Variant value = Variant();
|
|
|
|
|
|
|
|
Type tTarget;
|
|
|
|
void* targetDataAddr = GetDataPtrAndType(target, out tTarget);
|
|
|
|
|
|
|
|
if (!tTarget.IsSubtypeOf(mTypeInstance))
|
|
|
|
Runtime.FatalError("Invalid type");
|
|
|
|
|
|
|
|
targetDataAddr = (uint8*)targetDataAddr + mFieldData.mDataOffset;
|
|
|
|
|
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
|
|
|
|
2019-11-29 09:24:13 -08:00
|
|
|
if (typeCode == TypeCode.Object)
|
2019-08-23 11:56:54 -07:00
|
|
|
{
|
2020-03-09 06:34:16 -07:00
|
|
|
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> GetValue()
|
|
|
|
{
|
|
|
|
Variant value = Variant();
|
|
|
|
|
|
|
|
//TODO: Assert static
|
|
|
|
|
|
|
|
if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
|
|
|
|
{
|
|
|
|
return Variant.Create(FieldType, &mFieldData.mConstValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
ThrowUnimplemented();
|
|
|
|
|
|
|
|
//Type tTarget;
|
|
|
|
#unwarn
|
|
|
|
void* targetDataAddr = (void*)(int)mFieldData.mConstValue;
|
|
|
|
|
2020-03-09 06:34:16 -07:00
|
|
|
Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
|
2020-06-23 07:32:53 -07:00
|
|
|
value.[Friend]mStructType = (int)Internal.UnsafeCastToPtr(fieldType);
|
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
|
|
|
|
|
|
|
if (typeCode == TypeCode.Int32)
|
|
|
|
{
|
2020-03-09 06:34:16 -07:00
|
|
|
*(int32*)&value.[Friend]mData = *(int32*)targetDataAddr;
|
2019-08-23 11:56:54 -07:00
|
|
|
}
|
|
|
|
else if (typeCode == TypeCode.Object)
|
|
|
|
{
|
2020-03-09 06:34:16 -07:00
|
|
|
value.[Friend]mStructType = 0;
|
|
|
|
value.[Friend]mData = (int)targetDataAddr;
|
2019-08-23 11:56:54 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return .Err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
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)
|
2019-08-23 11:56:54 -07:00
|
|
|
return false;
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Result<FieldInfo> GetNext() mut
|
|
|
|
{
|
|
|
|
if (!MoveNext())
|
|
|
|
return .Err;
|
|
|
|
return Current;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|