Files
Il2CppInspectorRedux/Il2CppInspector.Common/Next/Metadata/Il2CppMetadataUsage.cs

64 lines
2.0 KiB
C#

using System.Diagnostics;
using VersionedSerialization;
namespace Il2CppInspector.Next.Metadata;
using VersionedSerialization.Attributes;
using EncodedMethodIndex = uint;
[VersionedStruct]
public partial record struct Il2CppMetadataUsage
{
private const uint TypeMask = 0b111u << 29;
private const uint InflatedMask = 0b1;
private const uint IndexMask = ~(TypeMask | InflatedMask);
public readonly Il2CppMetadataUsageType Type => (Il2CppMetadataUsageType)((EncodedValue & TypeMask) >> 29);
public readonly uint Index => (EncodedValue & IndexMask) >> 1;
public readonly bool Inflated => (EncodedValue & InflatedMask) == 1;
public EncodedMethodIndex EncodedValue;
public static Il2CppMetadataUsage FromValue(in StructVersion version, uint encodedValue)
{
if (version >= MetadataVersions.V270)
{
return new Il2CppMetadataUsage
{
EncodedValue = encodedValue
};
}
if (version >= MetadataVersions.V190)
{
// Below v27 we need to fake the 'inflated' flag, so shift the value by one
var type = (encodedValue & TypeMask) >> 29;
var value = encodedValue & (IndexMask | 1);
Debug.Assert((value & 0x10000000) == 0);
return new Il2CppMetadataUsage
{
EncodedValue = (type << 29) | (value << 1)
};
}
/* These encoded indices appear only in vtables, and are decoded by IsGenericMethodIndex/GetDecodedMethodIndex */
var methodType = (encodedValue >> 31) != 0
? Il2CppMetadataUsageType.MethodRef
: Il2CppMetadataUsageType.MethodDef;
var index = encodedValue & 0x7FFFFFFF;
Debug.Assert((index & 0x60000000) == 0);
return new Il2CppMetadataUsage
{
EncodedValue = ((uint)methodType << 29) | (index << 1)
};
}
public readonly override string ToString()
{
return $"{Type} @ 0x{Index:X}";
}
}