aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/mcprepack/ParseMethodDescriptor.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/mcprepack/ParseMethodDescriptor.kt')
-rw-r--r--src/main/kotlin/mcprepack/ParseMethodDescriptor.kt112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/main/kotlin/mcprepack/ParseMethodDescriptor.kt b/src/main/kotlin/mcprepack/ParseMethodDescriptor.kt
new file mode 100644
index 0000000..a3d5717
--- /dev/null
+++ b/src/main/kotlin/mcprepack/ParseMethodDescriptor.kt
@@ -0,0 +1,112 @@
+package mcprepack
+
+import net.fabricmc.stitch.commands.tinyv2.TinyFile
+import java.io.StringReader
+
+sealed interface TypeDescriptor {
+ fun mapClassName(tinyFile: TinyFile): TypeDescriptor {
+ return when (this) {
+ is Class ->
+ Class(tinyFile.mapClassesByFirstNamespace()[this.name]?.classNames?.get(2) ?: this.name)
+
+ else -> this
+ }
+ }
+
+ fun toProguardString(): String {
+ return when (this) {
+ is Array -> this.elementType.toProguardString() + "[]"
+ Boolean -> "boolean"
+ Byte -> "byte"
+ Char -> "char"
+ is Class -> this.name.replace("/", ".")
+ Double -> "double"
+ Float -> "float"
+ Int -> "int"
+ Long -> "long"
+ Short -> "short"
+ Void -> "void"
+ }
+ }
+
+ sealed interface FieldDescriptor : TypeDescriptor
+ object Void : TypeDescriptor
+ object Double : FieldDescriptor
+ object Boolean : FieldDescriptor
+ object Float : FieldDescriptor
+ object Int : FieldDescriptor
+ object Long : FieldDescriptor
+ object Short : FieldDescriptor
+ object Byte : FieldDescriptor
+ object Char : FieldDescriptor
+ data class Class(val name: String) : FieldDescriptor
+ data class Array(val elementType: TypeDescriptor) : FieldDescriptor
+}
+
+data class FieldDescriptor(
+ val type: TypeDescriptor.FieldDescriptor
+) {
+ companion object {
+ fun parseFieldDescriptor(descriptor: String) =
+ FieldDescriptor(readType(StringReader(descriptor)) as? TypeDescriptor.FieldDescriptor ?: error("Cannot have void as a field type"))
+ }
+}
+
+data class MethodDescriptor(
+ val arguments: List<TypeDescriptor.FieldDescriptor>,
+ val returnType: TypeDescriptor
+) {
+ companion object {
+ fun parseMethodDescriptor(descriptor: String): MethodDescriptor {
+ val reader = StringReader(descriptor)
+ require(reader.readChar() == '(')
+ val arguments = mutableListOf<TypeDescriptor.FieldDescriptor>()
+ while (reader.peek() != ')') {
+ arguments.add(
+ readType(reader) as? TypeDescriptor.FieldDescriptor ?: error("Cannot have void type as argument")
+ )
+ }
+ reader.readChar() // Consume the ')'
+ return MethodDescriptor(arguments, readType(reader))
+ }
+ }
+}
+
+fun StringReader.readChar() = CharArray(1).let {
+ if (read(it) < 0) null
+ else it[0]
+}
+
+fun StringReader.readUntil(search: Char): String? {
+ val s = StringBuilder()
+ while (true) {
+ val justRead = readChar() ?: return null
+ if (justRead == search) return s.toString()
+ s.append(justRead)
+ }
+}
+
+fun StringReader.peek(): Char? {
+ mark(0)
+ val x = readChar()
+ reset()
+ return x
+}
+
+
+fun readType(reader: StringReader): TypeDescriptor {
+ return when (reader.readChar()) {
+ 'L' -> TypeDescriptor.Class(reader.readUntil(';') ?: error("Unfinished class type descriptor"))
+ 'V' -> TypeDescriptor.Void
+ 'Z' -> TypeDescriptor.Boolean
+ 'B' -> TypeDescriptor.Byte
+ 'I' -> TypeDescriptor.Int
+ 'D' -> TypeDescriptor.Double
+ 'J' -> TypeDescriptor.Long
+ 'S' -> TypeDescriptor.Short
+ 'F' -> TypeDescriptor.Float
+ 'C' -> TypeDescriptor.Char
+ '[' -> TypeDescriptor.Array(readType(reader))
+ else -> error("Unknown or unfinished type descriptor")
+ }
+}