summaryrefslogtreecommitdiff
path: root/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java
blob: 773c95eb7e4390952caf0fce258bf05c8cf8e19a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package cuchaz.enigma.translation.mapping.serde;

import com.google.common.base.Charsets;
import cuchaz.enigma.ProgressListener;
import cuchaz.enigma.throwables.MappingParseException;
import cuchaz.enigma.translation.mapping.EntryMapping;
import cuchaz.enigma.translation.mapping.MappingPair;
import cuchaz.enigma.translation.mapping.MappingSaveParameters;
import cuchaz.enigma.translation.mapping.tree.EntryTree;
import cuchaz.enigma.translation.mapping.tree.HashEntryTree;
import cuchaz.enigma.translation.representation.MethodDescriptor;
import cuchaz.enigma.translation.representation.TypeDescriptor;
import cuchaz.enigma.translation.representation.entry.ClassEntry;
import cuchaz.enigma.translation.representation.entry.FieldEntry;
import cuchaz.enigma.translation.representation.entry.LocalVariableEntry;
import cuchaz.enigma.translation.representation.entry.MethodEntry;
import cuchaz.enigma.utils.I18n;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

public enum TinyMappingsReader implements MappingsReader {
	INSTANCE;

	@Override
	public EntryTree<EntryMapping> read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException {
		return read(path, Files.readAllLines(path, Charsets.UTF_8), progress);
	}

	private EntryTree<EntryMapping> read(Path path, List<String> lines, ProgressListener progress) throws MappingParseException {
		EntryTree<EntryMapping> mappings = new HashEntryTree<>();
		lines.remove(0);

		progress.init(lines.size(), I18n.translate("progress.mappings.tiny_file.loading"));

		for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) {
			progress.step(lineNumber, "");

			String line = lines.get(lineNumber);

			if (line.trim().startsWith("#")) {
				continue;
			}

			try {
				MappingPair<?, EntryMapping> mapping = parseLine(line);
				mappings.insert(mapping.getEntry(), mapping.getMapping());
			} catch (Throwable t) {
				t.printStackTrace();
				throw new MappingParseException(path::toString, lineNumber, t.toString());
			}
		}

		return mappings;
	}

	private MappingPair<?, EntryMapping> parseLine(String line) {
		String[] tokens = line.split("\t");

		String key = tokens[0];
		switch (key) {
			case "CLASS":
				return parseClass(tokens);
			case "FIELD":
				return parseField(tokens);
			case "METHOD":
				return parseMethod(tokens);
			case "MTH-ARG":
				return parseArgument(tokens);
			default:
				throw new RuntimeException("Unknown token '" + key + "'!");
		}
	}

	private MappingPair<ClassEntry, EntryMapping> parseClass(String[] tokens) {
		ClassEntry obfuscatedEntry = new ClassEntry(tokens[1]);
		String mapping = tokens[2];
		if (mapping.indexOf('$') > 0) {
			// inner classes should map to only the final part
			mapping = mapping.substring(mapping.lastIndexOf('$') + 1);
		}
		return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping));
	}

	private MappingPair<FieldEntry, EntryMapping> parseField(String[] tokens) {
		ClassEntry ownerClass = new ClassEntry(tokens[1]);
		TypeDescriptor descriptor = new TypeDescriptor(tokens[2]);

		FieldEntry obfuscatedEntry = new FieldEntry(ownerClass, tokens[3], descriptor);
		String mapping = tokens[4];
		return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping));
	}

	private MappingPair<MethodEntry, EntryMapping> parseMethod(String[] tokens) {
		ClassEntry ownerClass = new ClassEntry(tokens[1]);
		MethodDescriptor descriptor = new MethodDescriptor(tokens[2]);

		MethodEntry obfuscatedEntry = new MethodEntry(ownerClass, tokens[3], descriptor);
		String mapping = tokens[4];
		return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping));
	}

	private MappingPair<LocalVariableEntry, EntryMapping> parseArgument(String[] tokens) {
		ClassEntry ownerClass = new ClassEntry(tokens[1]);
		MethodDescriptor ownerDescriptor = new MethodDescriptor(tokens[2]);
		MethodEntry ownerMethod = new MethodEntry(ownerClass, tokens[3], ownerDescriptor);
		int variableIndex = Integer.parseInt(tokens[4]);

		String mapping = tokens[5];
		LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true, null);
		return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping));
	}
}