mirror of
https://github.com/AssetRipper/Cpp2IL.git
synced 2026-11-13 04:26:33 -10:00
92 lines
3.3 KiB
C#
92 lines
3.3 KiB
C#
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Cpp2IL.Core.Extensions;
|
|
using Cpp2IL.Core.Model.Contexts;
|
|
using Cpp2IL.Core.Utils;
|
|
using LibCpp2IL.BinaryStructures;
|
|
|
|
namespace Cpp2IL.Core.Model.CustomAttributes;
|
|
|
|
|
|
/// <summary>
|
|
/// Represents a custom attribute parameter which is an array of other parameters, which can themselves potentially be arrays, enums, etc.
|
|
///
|
|
/// When parsing this, first check IsNullArray - if it's true, emit a null and continue.
|
|
///
|
|
/// Then check EnumType - if it's non-null, it means this is an enum array, not a simple primitive array, and the type of the enum should be used when emitting.
|
|
///
|
|
/// If it's null, use ArrType to determine the type of the array, which will be a primitive, string, or type.
|
|
///
|
|
/// Then read the ArrayElements list and output each one. Remember to type-prefix if ArrType is Object.
|
|
/// </summary>
|
|
public class CustomAttributeArrayParameter : BaseCustomAttributeParameter
|
|
{
|
|
public bool IsNullArray;
|
|
public Il2CppType? EnumType;
|
|
|
|
public Il2CppTypeEnum ArrType;
|
|
|
|
public List<BaseCustomAttributeParameter> ArrayElements = new();
|
|
|
|
public CustomAttributeArrayParameter(AnalyzedCustomAttribute owner, CustomAttributeParameterKind kind, int index) : base(owner, kind, index)
|
|
{
|
|
}
|
|
|
|
public override void ReadFromV29Blob(BinaryReader reader, ApplicationAnalysisContext context)
|
|
{
|
|
var arrLength = reader.BaseStream.ReadUnityCompressedInt();
|
|
if (arrLength == -1)
|
|
{
|
|
//Array length is -1 when the array itself is null
|
|
IsNullArray = true;
|
|
return;
|
|
}
|
|
|
|
ArrType = (Il2CppTypeEnum) reader.ReadByte();
|
|
if (ArrType == Il2CppTypeEnum.IL2CPP_TYPE_ENUM)
|
|
{
|
|
var enumTypeIndex = reader.BaseStream.ReadUnityCompressedInt();
|
|
|
|
//Save the actual enum type for later.
|
|
EnumType = context.Binary.GetType(enumTypeIndex);
|
|
|
|
//We read as the primitive underlying type.
|
|
var enumClass = EnumType.AsClass();
|
|
ArrType = enumClass.EnumUnderlyingType.Type;
|
|
}
|
|
|
|
var arrayElementsAreTypePrefixed = reader.ReadBoolean();
|
|
|
|
if(arrayElementsAreTypePrefixed && ArrType != Il2CppTypeEnum.IL2CPP_TYPE_OBJECT)
|
|
throw new("Array elements are type-prefixed, but the array type is not object");
|
|
|
|
for (var i = 0; i < arrLength; i++)
|
|
{
|
|
var thisType = ArrType;
|
|
|
|
if(arrayElementsAreTypePrefixed)
|
|
thisType = (Il2CppTypeEnum) reader.ReadByte();
|
|
|
|
//ConstructParameterForType will handle reading the enum type
|
|
var arrayElement = V29AttributeUtils.ConstructParameterForType(reader, context, thisType, Owner, CustomAttributeParameterKind.ArrayElement, i);
|
|
|
|
arrayElement.ReadFromV29Blob(reader, context);
|
|
|
|
ArrayElements.Add(arrayElement);
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
if (IsNullArray)
|
|
return "(array) null";
|
|
|
|
var arrType = ArrType.ToString();
|
|
if (EnumType != null)
|
|
arrType = EnumType.AsClass().ToString();
|
|
|
|
return $"new {arrType}[] {{{string.Join(", ", ArrayElements.Select(x => x.ToString()))}}}]";
|
|
}
|
|
}
|