initial "implementation" of the reflection tools. Only a mapping explorer for now.

This commit is contained in:
FalsePattern committed 2022-07-25 18:02:01 +02:00
1 parent 7f1e4fe2c3
commit f6faba4ffd
12 files changed
+22383

No files matched your search

@@ -0,0 +1,117 @@
package com.falsepattern.lib.internal;
import lombok.Getter;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Getter
class SRGGen {
private static class StringPair {
public final String name;
public final String desc;
private StringPair(String name, String desc) {
this.name = name;
this.desc = desc;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
StringPair that = (StringPair) o;
return name.equals(that.name) && desc.equals(that.desc);
}
@Override
public int hashCode() {
return Objects.hash(name, desc);
}
@Override
public String toString() {
return name + "," + desc;
}
}
private static Map<String, String> class_notch_srg = new HashMap<>();
private static Map<String, String> class_notch_mcp = new HashMap<>();
private static Map<String, String> class_srg_mcp = new HashMap<>();
private static Map<String, String> class_mcp_srg = new HashMap<>();
private static Map<String, String> class_mcp_notch = new HashMap<>();
private static Map<String, String> field_notch_srg = new HashMap<>();
private static Map<String, String> field_notch_mcp = new HashMap<>();
private static Map<String, String> field_srg_mcp = new HashMap<>();
private static Map<String, String> field_mcp_srg = new HashMap<>();
private static Map<String, String> field_mcp_notch = new HashMap<>();
private static Map<StringPair, StringPair> method_notch_srg = new HashMap<>();
private static Map<StringPair, StringPair> method_notch_mcp = new HashMap<>();
private static Map<StringPair, StringPair> method_srg_mcp = new HashMap<>();
private static Map<StringPair, StringPair> method_mcp_srg = new HashMap<>();
private static Map<StringPair, StringPair> method_mcp_notch = new HashMap<>();
public static void main(String[] args) throws IOException {
Path dir = Paths.get(args[0]);
parseLines(Files.readAllLines(dir.resolve("notch-srg.srg")), class_notch_srg, field_notch_srg, method_notch_srg);
parseLines(Files.readAllLines(dir.resolve("notch-mcp.srg")), class_notch_mcp, field_notch_mcp, method_notch_mcp);
parseLines(Files.readAllLines(dir.resolve("srg-mcp.srg")), class_srg_mcp, field_srg_mcp, method_srg_mcp);
parseLines(Files.readAllLines(dir.resolve("mcp-srg.srg")), class_mcp_srg, field_mcp_srg, method_mcp_srg);
parseLines(Files.readAllLines(dir.resolve("mcp-notch.srg")), class_mcp_notch, field_mcp_notch, method_mcp_notch);
try (OutputStream output = Files.newOutputStream(dir.resolve("classes.csv"))) {
output.write("notch,srg,mcp\n".getBytes(StandardCharsets.UTF_8));
crossValidate(class_notch_srg, class_notch_mcp, class_srg_mcp, class_mcp_srg, class_mcp_notch, output);
}
try (OutputStream output = Files.newOutputStream(dir.resolve("fields.csv"))) {
output.write("notch,srg,mcp\n".getBytes(StandardCharsets.UTF_8));
crossValidate(field_notch_srg, field_notch_mcp, field_srg_mcp, field_mcp_srg, field_mcp_notch, output);
}
try (OutputStream output = Files.newOutputStream(dir.resolve("methods.csv"))) {
output.write("notch,notchdesc,srg,srgdesc,mcp,mcpdesc\n".getBytes(StandardCharsets.UTF_8));
crossValidate(method_notch_srg, method_notch_mcp, method_srg_mcp, method_mcp_srg, method_mcp_notch, output);
}
}
private static boolean crossValidate(Map<?, ?> notch_srg, Map<?, ?> notch_mcp, Map<?, ?> srg_mcp, Map<?, ?> mcp_srg, Map<?, ?> mcp_notch, OutputStream output)
throws IOException {
for (Map.Entry<?, ?> notch_srg_entry: notch_srg.entrySet()) {
Object notch = notch_srg_entry.getKey();
Object srg = notch_srg_entry.getValue();
Object mcp = notch_mcp.get(notch);
if (!srg_mcp.get(srg).equals(mcp) ||
!mcp_srg.get(mcp).equals(srg) ||
!mcp_notch.get(mcp).equals(notch)) {
throw new RuntimeException(notch + " - " + srg + " - " + mcp);
}
output.write((notch + "," + srg + "," + mcp + "\n").getBytes(StandardCharsets.UTF_8));
}
return true;
}
private static void parseLines(List<String> lines, Map<String, String> classes, Map<String, String> fields, Map<StringPair, StringPair> methods) {
for (String line: lines) {
String[] parts = line.split(" ");
switch (parts[0]) {
case "CL:":
classes.put(parts[1], parts[2]);
break;
case "FD:":
fields.put(parts[1], parts[2]);
break;
case "MD:":
methods.put(new StringPair(parts[1], parts[2]), new StringPair(parts[3], parts[4]));
break;
}
}
}
}
@@ -0,0 +1,39 @@
package com.falsepattern.lib.reflection;
import com.falsepattern.lib.reflection.types.MappingType;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.util.Map;
import java.util.function.Function;
@Accessors(fluent = true)
@ToString
@EqualsAndHashCode
@Getter
public class MappedString {
public final String notch;
public final String srg;
public final String mcp;
public MappedString(String[] source, int offset, int stride, Function<String, String> remapper, Map<String, String> stringPool) {
notch = stringPool.computeIfAbsent(remapper.apply(source[offset ]), (str) -> str);
srg = stringPool.computeIfAbsent(remapper.apply(source[offset + stride ]), (str) -> str);
mcp = stringPool.computeIfAbsent(remapper.apply(source[offset + stride * 2]), (str) -> str);
}
public String get(@NonNull MappingType type) {
switch (type) {
case Notch:
return notch;
case SRG:
return srg;
case MCP:
return mcp;
default:
throw new IllegalArgumentException("Invalid enum value " + type);
}
}
}
@@ -0,0 +1,67 @@
package com.falsepattern.lib.reflection;
import com.falsepattern.lib.internal.FalsePatternLib;
import com.falsepattern.lib.reflection.storage.Lookup;
import com.falsepattern.lib.reflection.types.MappingType;
import com.falsepattern.lib.reflection.types.NameType;
import com.falsepattern.lib.util.ResourceUtil;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.val;
import java.io.IOException;
import java.util.HashMap;
public class MappingManager {
private static boolean initialized = false;
private static final Lookup<UniversalClass> internalLookup = new Lookup<>();
private static final Lookup<UniversalClass> regularLookup = new Lookup<>();
@SneakyThrows
private static synchronized void initialize() {
if (initialized) return;
initialized = true;
val stringPool = new HashMap<String, String>();
{
val classMappings = ResourceUtil.getResourceStringFromJar("/classes.csv", FalsePatternLib.class).split("\n");
for (int i = 1; i < classMappings.length; i++) {
val line = classMappings[i].split(",");
val clazz = new UniversalClass(line, stringPool);
internalLookup.unwrap(clazz.internalName, clazz);
regularLookup.unwrap(clazz.regularName, clazz);
}
}
{
val fieldMappings = ResourceUtil.getResourceStringFromJar("/fields.csv", FalsePatternLib.class).split("\n");
for (int i = 1; i < fieldMappings.length; i++) {
val line = fieldMappings[i].split(",");
val field = new UniversalField(line, stringPool);
val clazz = internalLookup.get(MappingType.Notch, line[0].substring(0, line[0].lastIndexOf('/')));
clazz.addField(field);
}
}
{
val methodMappings = ResourceUtil.getResourceStringFromJar("/methods.csv", FalsePatternLib.class).split("\n");
for (int i = 1; i < methodMappings.length; i++) {
val line = methodMappings[i].split(",");
val field = new UniversalMethod(line, stringPool);
val clazz = internalLookup.get(MappingType.Notch, line[0].substring(0, line[0].lastIndexOf('/')));
clazz.addMethod(field);
}
}
}
public static UniversalClass classForName(@NonNull NameType nameType, @NonNull MappingType mappingType, String className) {
initialize();
switch (nameType) {
case Internal:
return internalLookup.get(mappingType, className);
case Regular:
return regularLookup.get(mappingType, className);
default:
throw new IllegalArgumentException("Invalid enum value " + nameType);
}
}
}
@@ -0,0 +1,49 @@
package com.falsepattern.lib.reflection;
import com.falsepattern.lib.reflection.storage.Lookup;
import com.falsepattern.lib.reflection.types.MappingType;
import com.falsepattern.lib.reflection.types.NameType;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.util.Map;
@Accessors(fluent = true)
@ToString
@EqualsAndHashCode
public class UniversalClass {
@Getter
public final MappedString internalName;
@Getter
public final MappedString regularName;
private final Lookup<UniversalField> fields = new Lookup<>();
private final Lookup<UniversalMethod> methods = new Lookup<>();
public UniversalClass(String[] names, Map<String, String> stringPool) {
internalName = new MappedString(names, 0, 1, (str) -> str, stringPool);
regularName = new MappedString(names, 0, 1, (str) -> str.replace('/', '.'), stringPool);
}
public void addField(UniversalField field) {
fields.unwrap(field.name, field);
}
public void addMethod(UniversalMethod method) {
methods.unwrap(method.name, method);
}
public String getName(@NonNull NameType nameType, @NonNull MappingType mappingType) {
switch (nameType) {
case Internal:
return internalName.get(mappingType);
case Regular:
return regularName.get(mappingType);
default:
throw new IllegalArgumentException("Invalid enum value " + nameType);
}
}
}
@@ -0,0 +1,26 @@
package com.falsepattern.lib.reflection;
import com.falsepattern.lib.reflection.types.MappingType;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.util.Map;
@Accessors(fluent = true)
@ToString
@EqualsAndHashCode
public class UniversalField {
@Getter
public final MappedString name;
public UniversalField(String[] names, Map<String, String> stringPool) {
name = new MappedString(names, 0, 1, (str) -> str.substring(str.lastIndexOf('/') + 1), stringPool);
}
public String getName(@NonNull MappingType mappingType) {
return name.get(mappingType);
}
}
@@ -0,0 +1,33 @@
package com.falsepattern.lib.reflection;
import com.falsepattern.lib.reflection.types.MappingType;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.util.Map;
@Accessors(fluent = true)
@ToString
@EqualsAndHashCode
public class UniversalMethod {
@Getter
public final MappedString name;
@Getter
public final MappedString descriptor;
public UniversalMethod(String[] names, Map<String, String> stringPool) {
name = new MappedString(names, 0, 2, (str) -> str.substring(str.lastIndexOf('/') + 1), stringPool);
descriptor = new MappedString(names, 1, 2, (str) -> str, stringPool);
}
public String getName(@NonNull MappingType mappingType) {
return name.get(mappingType);
}
public String getDescriptor(@NonNull MappingType mappingType) {
return descriptor.get(mappingType);
}
}
@@ -0,0 +1,37 @@
package com.falsepattern.lib.reflection.storage;
import com.falsepattern.lib.reflection.MappedString;
import com.falsepattern.lib.reflection.types.MappingType;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.experimental.Accessors;
import java.util.HashMap;
import java.util.Map;
@Accessors(fluent = true)
@EqualsAndHashCode
public class Lookup<T> {
private final Map<String, T> notch = new HashMap<>();
private final Map<String, T> srg = new HashMap<>();
private final Map<String, T> mcp = new HashMap<>();
public void unwrap(MappedString mappedString, T value) {
notch.put(mappedString.notch, value);
srg.put(mappedString.srg, value);
mcp.put(mappedString.mcp, value);
}
public T get(@NonNull MappingType mappingType, @NonNull String key) {
switch (mappingType) {
case Notch:
return notch.get(key);
case SRG:
return srg.get(key);
case MCP:
return mcp.get(key);
default:
throw new IllegalArgumentException("Invalid enum value " + mappingType);
}
}
}
@@ -0,0 +1,7 @@
package com.falsepattern.lib.reflection.types;
public enum MappingType {
Notch,
SRG,
MCP
}
@@ -0,0 +1,6 @@
package com.falsepattern.lib.reflection.types;
public enum NameType {
Internal,
Regular
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff