AssetRipper_AssetRipper/Source/AssetRipper.AssemblyDumper/Passes/Pass203_OffsetPtrImplicitConversions.cs
2025-09-17 16:40:02 -07:00

60 lines
2.1 KiB
C#

namespace AssetRipper.AssemblyDumper.Passes;
/// <summary>
/// Adds implicit conversion and ToString override to OffsetPtr types.
/// </summary>
public static class Pass203_OffsetPtrImplicitConversions
{
const MethodAttributes ConversionAttributes = MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
public static void DoPass()
{
foreach ((string name, SubclassGroup group) in SharedState.Instance.SubclassGroups)
{
if (name.StartsWith("OffsetPtr"))
{
foreach (TypeDefinition type in group.Types)
{
type.AddImplicitConversion();
type.AddToStringOverride();
}
}
}
}
private static void AddImplicitConversion(this TypeDefinition type)
{
FieldDefinition field = type.GetField();
MethodDefinition implicitMethod = type.AddMethod("op_Implicit", ConversionAttributes, field.Signature!.FieldType);
implicitMethod.AddParameter(type.ToTypeSignature(), "value");
CilInstructionCollection instructions = implicitMethod.CilMethodBody!.Instructions;
instructions.Add(CilOpCodes.Ldarg_0);
instructions.Add(CilOpCodes.Ldfld, field);
instructions.Add(CilOpCodes.Ret);
}
private static void AddToStringOverride(this TypeDefinition type)
{
const MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot | MethodAttributes.HideBySig;
CorLibTypeSignature stringType = type.DeclaringModule!.CorLibTypeFactory.String;
ITypeDefOrRef objectType = type.DeclaringModule.CorLibTypeFactory.Object.ToTypeDefOrRef();
MethodDefinition toStringMethod = type.AddMethod(nameof(ToString), attributes, stringType);
CilInstructionCollection instructions = toStringMethod.CilMethodBody!.Instructions;
instructions.Add(CilOpCodes.Ldarg_0);
instructions.Add(CilOpCodes.Ldfld, type.GetField());
instructions.Add(CilOpCodes.Callvirt, new MemberReference(objectType, nameof(ToString), MethodSignature.CreateInstance(stringType)));
instructions.Add(CilOpCodes.Ret);
}
private static FieldDefinition GetField(this TypeDefinition type)
{
return type.Fields.Single(field => field.Name == "m_Data");
}
}