123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563 |
- using System.Collections;
- namespace System.Reflection
- {
- [CRepr, AlwaysInclude]
- public struct FieldInfo
- {
- public enum Error
- {
- InvalidTargetType,
- InvalidValueType
- }
- TypeInstance mTypeInstance;
- TypeInstance.FieldData* mFieldData;
- public this(TypeInstance typeInstance, TypeInstance.FieldData* fieldData)
- {
- mTypeInstance = typeInstance;
- mFieldData = fieldData;
- }
- public int32 MemberOffset
- {
- get
- {
- return (int32)mFieldData.mData;
- }
- }
- public Type FieldType
- {
- get
- {
- return Type.[Friend]GetType(mFieldData.mFieldTypeId);
- }
- }
- public bool IsConst
- {
- get
- {
- return mFieldData.mFlags.HasFlag(.Const);
- }
- }
- public bool IsStatic
- {
- get
- {
- return mFieldData.mFlags.HasFlag(.Static);
- }
- }
- public bool IsInstanceField
- {
- get
- {
- return !mFieldData.mFlags.HasFlag(.Static) && !mFieldData.mFlags.HasFlag(.Const);
- }
- }
- public StringView Name
- {
- get
- {
- return mFieldData.mName;
- }
- }
- public Result<void, Error> SetValue(Object obj, Object value)
- {
- void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj));
- if (mTypeInstance.IsStruct)
- {
- Type boxedType = obj.[Friend]RawGetType();
- bool typeMatched = false;
- if (boxedType.IsBoxed)
- {
- if (mTypeInstance == boxedType.UnderlyingType)
- {
- dataAddr = (void*)((int)dataAddr + boxedType.[Friend]mMemberDataOffset);
- if (boxedType.IsBoxedStructPtr)
- dataAddr = *(void**)dataAddr;
- typeMatched = true;
- }
- }
- if (!typeMatched)
- return .Err(.InvalidTargetType); // "Invalid target type");
- }
- 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(Object obj, Variant value)
- {
- void* dataAddr = ((uint8*)Internal.UnsafeCastToPtr(obj));
- if (mTypeInstance.IsStruct)
- {
- Type boxedType = obj.[Friend]RawGetType();
- bool typeMatched = false;
- if (boxedType.IsBoxed)
- {
- if (mTypeInstance == boxedType.UnderlyingType)
- {
- dataAddr = (void*)((int)dataAddr + boxedType.[Friend]mMemberDataOffset);
- if (boxedType.IsBoxedStructPtr)
- dataAddr = *(void**)dataAddr;
- typeMatched = true;
- }
- }
- if (!typeMatched)
- return .Err(.InvalidTargetType);
- }
- 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);
- }
- 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);
- }
- value.CopyValueData(dataAddr);
- return .Ok;
- }
-
- static mixin Decode<T2>(void* data)
- {
- *((*(T2**)&data)++)
- }
- public Result<T> GetCustomAttribute<T>() where T : Attribute
- {
- return mTypeInstance.[Friend]GetCustomAttribute<T>(mFieldData.mCustomAttributesIdx);
- }
- void* GetDataPtrAndType(Object value, out Type type)
- {
- type = value.[Friend]RawGetType();
- if (type.IsBoxedStructPtr)
- return *(void**)(((uint8*)Internal.UnsafeCastToPtr(value)) + type.[Friend]mMemberDataOffset);
- if (type.IsBoxed)
- return ((uint8*)Internal.UnsafeCastToPtr(value)) + type.[Friend]mMemberDataOffset;
- return ((uint8*)Internal.UnsafeCastToPtr(value));
- }
- public Result<void, Error> GetValue<TMember>(Object target, out TMember value)
- {
- value = default(TMember);
- void* targetDataAddr;
- if (target == null)
- {
- if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
- {
- // Unhandled
- return .Err(.InvalidTargetType);
- }
- if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
- return .Err(.InvalidTargetType);
- targetDataAddr = null;
- }
- else
- {
- Type tTarget;
- targetDataAddr = GetDataPtrAndType(target, out tTarget);
- if (!tTarget.IsSubtypeOf(mTypeInstance))
- return .Err(.InvalidTargetType); //"Invalid type");
- }
-
- Type tMember = typeof(TMember);
- targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData;
-
- Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
- if (tMember.[Friend]mTypeCode == TypeCode.Object)
- {
- value = *(TMember*)targetDataAddr;
- }
- else if (fieldType.[Friend]mTypeCode == tMember.[Friend]mTypeCode)
- {
- Internal.MemCpy(&value, targetDataAddr, tMember.Size);
- }
- else
- {
- return .Err(.InvalidValueType);
- }
-
- return .Ok;
- }
- Result<Variant> GetValue(void* startTargetDataAddr, Type tTarget)
- {
- Variant value = Variant();
- void* targetDataAddr = startTargetDataAddr;
- if (targetDataAddr == null)
- {
- if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
- {
- return Variant.Create(FieldType, &mFieldData.mData);
- }
- if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
- return .Err;
- }
- else
- {
- if (!tTarget.IsSubtypeOf(mTypeInstance))
- return .Err; //Invalid type;
- }
- targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData;
- Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
- TypeCode typeCode = fieldType.[Friend]mTypeCode;
- if (typeCode == TypeCode.Enum)
- typeCode = fieldType.UnderlyingType.[Friend]mTypeCode;
- if (typeCode == TypeCode.Object)
- {
- value.[Friend]mStructType = 0;
- value.[Friend]mData = *(int*)targetDataAddr;
- }
- 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)
- {
- if (mFieldData.mFlags.HasFlag(FieldFlags.Const))
- {
- return Variant.Create(FieldType, &mFieldData.mData);
- }
- if (!mFieldData.mFlags.HasFlag(FieldFlags.Static))
- return .Err;
- targetDataAddr = null;
- }
- else
- {
- if (!tTarget.IsSubtypeOf(mTypeInstance))
- return .Err; //Invalid type;
- }
- targetDataAddr = (uint8*)targetDataAddr + (int)mFieldData.mData;
- Type fieldType = Type.[Friend]GetType(mFieldData.mFieldTypeId);
- TypeCode typeCode = fieldType.[Friend]mTypeCode;
- if (typeCode == TypeCode.Enum)
- typeCode = fieldType.UnderlyingType.[Friend]mTypeCode;
- value = Variant.CreateReference(fieldType, targetDataAddr);
- 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>
- {
- BindingFlags mBindingFlags;
- TypeInstance mTypeInstance;
- int32 mIdx;
- public this(TypeInstance typeInst, BindingFlags bindingFlags)
- {
- 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)
- return false;
- var fieldData = &mTypeInstance.[Friend]mFieldDataPtr[mIdx];
- 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];
- return FieldInfo(mTypeInstance, fieldData);
- }
- }
- public int32 Index
- {
- get
- {
- return mIdx;
- }
- }
- public Result<FieldInfo> GetNext() mut
- {
- if (!MoveNext())
- return .Err;
- return Current;
- }
- }
- }
- }
|