Skip to content

Commit

Permalink
Merge upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
NebelNidas committed Mar 7, 2024
2 parents f5f0568 + 1046304 commit a10aeeb
Show file tree
Hide file tree
Showing 67 changed files with 2,933 additions and 479 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
- Added CSRG writer
- Added TSRG and TSRG2 writer
- Added JAM reader and writer
- Added JOBF reader and writer
- Added Recaf Simple reader and writer
- Added `OuterClassNameInheritingVisitor`
- Added `MappingFormat#hasWriter` boolean
- Added CSRG detection via the path-based API

## [0.5.1] - 2023-11-30
- Improved documentation
- Fixed ProGuard writer producing invalid files when missing destination names
- Fixed Enigma reader throwing incorrect error message
- Fixed NPE in `MemoryMappingTree`
- Fixed TSRG2 reader not handling multiple passes correctly

## [0.5.0] - 2023-11-15
- Actually marked `HierarchyInfoProvider` as experimental
- Added changelog
Expand Down
29 changes: 22 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ Mapping-IO is a small and efficient library for working with deobfuscation mappi

The API is inspired by ObjectWeb's [ASM](https://asm.ow2.io/): At its core, Mapping-IO is [visitor-based](./src/main/java/net/fabricmc/mappingio/MappingVisitor.java), but it also provides a [tree API](./src/main/java/net/fabricmc/mappingio/tree/) for in-memory storage and easier data manipulation.

Utilities for more sophisticated use cases can be found in the [mapping-io-extras](./mapping-io-extras/) module; they've been moved out from the core publication due to their additional dependency requirements.
Utilities for more sophisticated use cases can be found in the [mapping-io-extras](./mapping-io-extras/) module; they've been moved out from the core publication due to their additional dependencies.


## Usage
Reading and writing can be easily be achieved via the [`MappingReader`](./src/main/java/net/fabricmc/mappingio/MappingReader.java) and [`MappingWriter`](./src/main/java/net/fabricmc/mappingio/MappingWriter.java) interfaces:
Reading and writing can be easily achieved via the [`MappingReader`](./src/main/java/net/fabricmc/mappingio/MappingReader.java) and [`MappingWriter`](./src/main/java/net/fabricmc/mappingio/MappingWriter.java) interfaces:
```java
MappingReader.read(inputPath, /* optional */ inputFormat,
MappingWriter.create(outputPath, outputFormat));
```

The above example reads mappings from the input path directly into a mapping writer, writing all contents to disk in the specified mapping format.
Keep in mind that the conversion process might be lossy if the two formats' feature sets differ; see the comparison table [here](./src/main/java/net/fabricmc/mappingio/format/MappingFormat.java) for more information.
The above example reads mappings from the input path directly into a `MappingWriter`, writing all contents to disk in the specified format.
Keep in mind that the conversion process might be lossy if the two formats' feature sets differ; see the comparison table [here](./src/main/java/net/fabricmc/mappingio/format/MappingFormat.java) for more details.

You can also read into a tree first:
```java
Expand All @@ -25,8 +25,23 @@ MappingReader.read(inputPath, inputFormat, tree);
tree.accept(MappingWriter.create(outputPath, outputFormat));
```

If the input format is known and more direct control over specific reading parameters is desired, the formats' readers (or writers) may also be invoked directly.
If the input format is known beforehand and more direct control over specific reading parameters is desired, the formats' readers (or writers) may also be invoked directly.

Mapping manipulation is achieved either via the tree API and/or specialized `MappingVisitor`s, hand-crafted or using pre-made ones found in the [adapter](./src/main/java/net/fabricmc/mappingio/adapter/) package.
Mapping manipulation is achieved either via the tree API or specialized `MappingVisitor`s, hand-crafted or utilizing first-party ones found in the [adapter](./src/main/java/net/fabricmc/mappingio/adapter/) package.

For more information, please consult the project's Javadoc comments.
For further information, please consult the project's Javadocs.


### Maven
Mapping-IO is available from the [FabricMC Maven](https://maven.fabricmc.net/net/fabricmc/mapping-io), version 0.4.2 and onwards can also be found on Maven Central.

Gradle snippet:
```gradle
repositories {
mavenCentral()
}
dependencies {
api 'net.fabricmc:mapping-io:${mappingio_version}'
}
```
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
org.gradle.jvmargs = -Xmx2G

# Project properties
version = 0.5.0
version = 0.5.1

# Dependencies
asm_version = 9.6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import net.fabricmc.mappingio.tree.MappingTreeView;

/**
* An ASM remapper that remaps between two namespaces in a {@link MappingTreeView}.
* An ASM {@link Remapper} that remaps between two namespaces in a {@link MappingTreeView}.
*/
public final class MappingTreeRemapper extends Remapper {
private final MappingTreeView tree;
Expand All @@ -33,9 +33,9 @@ public final class MappingTreeRemapper extends Remapper {
/**
* Constructs a {@code MappingTreeRemapper}.
*
* @param tree the mapping tree view
* @param from the input namespace, must be in the tree
* @param to the output namespace, must be in the tree
* @param tree The mapping tree view.
* @param from The input namespace, must be in the tree.
* @param to The output namespace, must be in the tree.
*/
public MappingTreeRemapper(MappingTreeView tree, String from, String to) {
Objects.requireNonNull(tree, "Mapping tree cannot be null");
Expand Down
10 changes: 7 additions & 3 deletions src/main/java/net/fabricmc/mappingio/FlatMappingVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
import net.fabricmc.mappingio.adapter.FlatAsRegularMappingVisitor;
import net.fabricmc.mappingio.adapter.RegularAsFlatMappingVisitor;

/**
* A mapping visitor that provides the entire data for a given element within a single visit call.
*/
public interface FlatMappingVisitor {
default Set<MappingFlag> getFlags() {
return MappingFlag.NONE;
Expand All @@ -40,7 +43,7 @@ default void reset() {
/**
* Determine whether the header (namespaces, metadata if part of the header) should be visited.
*
* @return true if the header is to be visited, false otherwise
* @return {@code true} if the header is to be visited, {@code false} otherwise.
*/
default boolean visitHeader() throws IOException {
return true;
Expand All @@ -53,7 +56,7 @@ default void visitMetadata(String key, @Nullable String value) throws IOExceptio
/**
* Determine whether the mapping content (classes and anything below, metadata if not part of the header) should be visited.
*
* @return true if content is to be visited, false otherwise
* @return {@code true} if content is to be visited, {@code false} otherwise.
*/
default boolean visitContent() throws IOException {
return true;
Expand Down Expand Up @@ -96,7 +99,8 @@ void visitMethodVarComment(String srcClsName, String srcMethodName, @Nullable St

/**
* Finish the visitation pass.
* @return true if the visitation pass is final, false if it should be started over
*
* @return {@code true} if the visitation pass is final, {@code false} if it should be started over.
*/
default boolean visitEnd() throws IOException {
return true;
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/net/fabricmc/mappingio/MappedElementKind.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

package net.fabricmc.mappingio;

/**
* A kind of element that can be mapped.
*/
public enum MappedElementKind {
CLASS(0),
FIELD(1),
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/net/fabricmc/mappingio/MappingFlag.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import java.util.EnumSet;
import java.util.Set;

/**
* Flags a {@link MappingVisitor} may provide to inform the caller about certain requirements.
*/
public enum MappingFlag {
/**
* Indication that the visitor may require multiple passes.
Expand Down
73 changes: 64 additions & 9 deletions src/main/java/net/fabricmc/mappingio/MappingReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
import net.fabricmc.mappingio.format.MappingFormat;
import net.fabricmc.mappingio.format.enigma.EnigmaDirReader;
import net.fabricmc.mappingio.format.enigma.EnigmaFileReader;
import net.fabricmc.mappingio.format.jobf.JobfFileReader;
import net.fabricmc.mappingio.format.proguard.ProGuardFileReader;
import net.fabricmc.mappingio.format.simple.RecafSimpleFileReader;
import net.fabricmc.mappingio.format.srg.JamFileReader;
import net.fabricmc.mappingio.format.srg.SrgFileReader;
import net.fabricmc.mappingio.format.srg.TsrgFileReader;
import net.fabricmc.mappingio.format.tiny.Tiny1FileReader;
Expand Down Expand Up @@ -66,7 +69,7 @@ private static MappingFormat detectFormat(Reader reader, @Nullable String fileEx
int pos = 0;
int len;

// Be careful not to close the reader, thats upto the caller.
// Be careful not to close the reader, that's up to the caller.
BufferedReader br = reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader);

br.mark(DETECT_HEADER_LEN);
Expand All @@ -90,14 +93,25 @@ private static MappingFormat detectFormat(Reader reader, @Nullable String fileEx
return MappingFormat.ENIGMA_FILE;
case "PK:":
case "CL:":
case "MD:":
case "FD:":
case "MD:":
return detectSrgOrXsrg(br, fileExt);
case "CL ":
case "FD ":
case "MD ":
case "MP ":
return MappingFormat.JAM_FILE;
}

String headerStr = String.valueOf(buffer, 0, pos);

if (headerStr.contains(" -> ")) {
if ((headerStr.startsWith("p ")
|| headerStr.startsWith("c ")
|| headerStr.startsWith("f ")
|| headerStr.startsWith("m "))
&& headerStr.contains(" = ")) {
return MappingFormat.JOBF_FILE;
} else if (headerStr.contains(" -> ")) {
return MappingFormat.PROGUARD_FILE;
} else if (headerStr.contains("\n\t")) {
return MappingFormat.TSRG_FILE;
Expand All @@ -107,6 +121,8 @@ private static MappingFormat detectFormat(Reader reader, @Nullable String fileEx
if (fileExt.equals(MappingFormat.CSRG_FILE.fileExt)) return MappingFormat.CSRG_FILE;
}

// TODO: Recaf Simple

return null; // format unknown, not easily detectable or corrupted
}

Expand Down Expand Up @@ -187,35 +203,65 @@ public static List<String> getNamespaces(Reader reader, MappingFormat format) th
}
}

public static void read(Path file, MappingVisitor visitor) throws IOException {
read(file, null, visitor);
/**
* Tries to detect the format of the given path and read it.
*
* @param path The path to read from. Can be a file or a directory.
* @param visitor The receiving visitor.
* @throws IOException If the format can't be detected or reading fails.
*/
public static void read(Path path, MappingVisitor visitor) throws IOException {
read(path, null, visitor);
}

public static void read(Path file, MappingFormat format, MappingVisitor visitor) throws IOException {
/**
* Tries to read the given path using the passed format's reader.
*
* @param path The path to read from. Can be a file or a directory.
* @param format The format to use. Has to match the path's format.
* @param visitor The receiving visitor.
* @throws IOException If reading fails.
*/
public static void read(Path path, MappingFormat format, MappingVisitor visitor) throws IOException {
if (format == null) {
format = detectFormat(file);
format = detectFormat(path);
if (format == null) throw new IOException("invalid/unsupported mapping format");
}

if (format.hasSingleFile()) {
try (Reader reader = Files.newBufferedReader(file)) {
try (Reader reader = Files.newBufferedReader(path)) {
read(reader, format, visitor);
}
} else {
switch (format) {
case ENIGMA_DIR:
EnigmaDirReader.read(file, visitor);
EnigmaDirReader.read(path, visitor);
break;
default:
throw new IllegalStateException();
}
}
}

/**
* Tries to detect the reader's content's format and read it.
*
* @param reader The reader to read from.
* @param visitor The receiving visitor.
* @throws IOException If the format can't be detected or reading fails.
*/
public static void read(Reader reader, MappingVisitor visitor) throws IOException {
read(reader, null, visitor);
}

/**
* Tries to read the reader's content using the passed format's mapping reader.
*
* @param reader The reader to read from.
* @param format The format to use. Has to match the reader's content's format.
* @param visitor The receiving visitor.
* @throws IOException If reading fails.
*/
public static void read(Reader reader, MappingFormat format, MappingVisitor visitor) throws IOException {
if (format == null) {
if (!reader.markSupported()) reader = new BufferedReader(reader);
Expand All @@ -241,6 +287,9 @@ public static void read(Reader reader, MappingFormat format, MappingVisitor visi
case XSRG_FILE:
SrgFileReader.read(reader, visitor);
break;
case JAM_FILE:
JamFileReader.read(reader, visitor);
break;
case CSRG_FILE:
case TSRG_FILE:
case TSRG_2_FILE:
Expand All @@ -249,6 +298,12 @@ public static void read(Reader reader, MappingFormat format, MappingVisitor visi
case PROGUARD_FILE:
ProGuardFileReader.read(reader, visitor);
break;
case RECAF_SIMPLE_FILE:
RecafSimpleFileReader.read(reader, visitor);
break;
case JOBF_FILE:
JobfFileReader.read(reader, visitor);
break;
default:
throw new IllegalStateException();
}
Expand Down
Loading

0 comments on commit a10aeeb

Please sign in to comment.