Files
JCIL/JavaClass/Constants.cs
T

158 lines
4.9 KiB
C#
Raw Normal View History

2026-05-05 22:41:02 +02:00
using System.Text;
namespace JCIL.Java.Class;
public enum ConstantType
{
Class = 7,
FieldRef = 9,
MethodRef = 10,
InterfaceMethodRef = 11,
String = 8,
Integer = 3,
Float = 4,
Long = 5,
Double = 6,
NameAndType = 12,
Utf8 = 1,
MethodHandle = 15,
MethodType = 16,
InvokeDynamic = 18,
}
public sealed record NameAndType(string Name, string Descriptor);
public sealed record MethodRef(Class Class, NameAndType Method);
public sealed record FieldRef(Class Class, NameAndType Field);
public record struct Constant(ConstantType Type, object Value)
{
public static Constant Read(Class self, TypeLoader loader, Reader reader)
{
object value;
var type = (ConstantType)reader.ReadUInt8();
switch (type)
{
case ConstantType.Class:
case ConstantType.String:
case ConstantType.MethodType:
{
value = reader.ReadUInt16();
break;
}
case ConstantType.Integer:
{
value = reader.ReadInt32();
break;
}
case ConstantType.Float:
{
value = reader.ReadFloat();
break;
}
case ConstantType.Long:
{
value = reader.ReadInt64();
break;
}
case ConstantType.Double:
{
value = reader.ReadDouble();
break;
}
case ConstantType.FieldRef:
case ConstantType.MethodRef:
case ConstantType.NameAndType:
case ConstantType.InvokeDynamic:
case ConstantType.InterfaceMethodRef:
{
value = (reader.ReadUInt16(), reader.ReadUInt16());
break;
}
case ConstantType.Utf8:
{
var length = reader.ReadUInt16();
var buffer = new byte[length];
reader.Stream.ReadExactly(buffer);
value = Encoding.UTF8.GetString(buffer);
break;
}
case ConstantType.MethodHandle:
{
value = (reader.ReadUInt8(), reader.ReadUInt16());
break;
}
default:
{
value = null!;
break;
}
}
return new Constant(type, value);
}
public static object? Resolve(TypeLoader loader, Constant[] constants, ushort i)
{
if (i == 0 || i > constants.Length) return null;
i -= 1;
switch (constants[i])
{
case { Type: ConstantType.Class, Value: ushort index }:
{
var name = (string) Resolve(loader, constants, index)!;
constants[i] = new Constant(ConstantType.Class, loader.GetClass(name.AsMemory()));
break;
}
case { Type: ConstantType.MethodRef, Value: (ushort classIndex, ushort nameTypeIndex) }:
{
var name = (Class)Resolve(loader, constants, classIndex)!;
var descriptor = (NameAndType)Resolve(loader, constants, nameTypeIndex)!;
constants[i] = new Constant(ConstantType.MethodRef, new MethodRef(name, descriptor));
break;
}
case { Type: ConstantType.FieldRef, Value: (ushort classIndex, ushort nameTypeIndex) }:
{
var name = (Class)Resolve(loader, constants, classIndex)!;
var descriptor = (NameAndType)Resolve(loader, constants, nameTypeIndex)!;
constants[i] = new Constant(ConstantType.FieldRef, new FieldRef(name, descriptor));
break;
}
case { Type: ConstantType.InterfaceMethodRef, Value: (ushort classIndex, ushort nameTypeIndex) }:
{
var name = (Class)Resolve(loader, constants, classIndex)!;
var descriptor = (NameAndType)Resolve(loader, constants, nameTypeIndex)!;
constants[i] = new Constant(ConstantType.InterfaceMethodRef, new MethodRef(name, descriptor));
break;
}
case { Type: ConstantType.String, Value: ushort index }:
{
var text = (string)Resolve(loader, constants, index)!;
constants[i] = new Constant(ConstantType.String, text);
break;
}
case { Type: ConstantType.NameAndType, Value: (ushort nameIndex, ushort descriptorIndex) }:
{
var name = (string)Resolve(loader, constants, nameIndex)!;
var descriptor = (string)Resolve(loader, constants, descriptorIndex)!;
constants[i] = new Constant(ConstantType.NameAndType, new NameAndType(name, descriptor));
break;
}
}
return constants[i].Value;
}
}