Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework the mapping read and write APIs #56

Draft
wants to merge 4 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 48 additions & 123 deletions src/main/java/net/fabricmc/mappingio/MappingReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package net.fabricmc.mappingio;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
Expand All @@ -26,20 +25,15 @@
import java.util.Arrays;
import java.util.List;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

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.proguard.ProGuardFileReader;
import net.fabricmc.mappingio.format.srg.SrgFileReader;
import net.fabricmc.mappingio.format.srg.TsrgFileReader;
import net.fabricmc.mappingio.format.tiny.Tiny1FileReader;
import net.fabricmc.mappingio.format.tiny.Tiny2FileReader;

public final class MappingReader {
private MappingReader() {
}

public static MappingFormat detectFormat(Path file) throws IOException {
@ApiStatus.NonExtendable
public interface MappingReader {
static MappingFormat detectFormat(Path file) throws IOException {
if (Files.isDirectory(file)) {
return MappingFormat.ENIGMA_DIR;
} else {
Expand All @@ -49,7 +43,8 @@ public static MappingFormat detectFormat(Path file) throws IOException {
}
}

public static MappingFormat detectFormat(Reader reader) throws IOException {
static MappingFormat detectFormat(Reader reader) throws IOException {
int DETECT_HEADER_LEN = 4096;
char[] buffer = new char[DETECT_HEADER_LEN];
int pos = 0;
int len;
Expand Down Expand Up @@ -88,126 +83,56 @@ public static MappingFormat detectFormat(Reader reader) throws IOException {
return null; // unknown format or corrupted
}

public static List<String> getNamespaces(Path file) throws IOException {
return getNamespaces(file, null);
}

public static List<String> getNamespaces(Path file, MappingFormat format) throws IOException {
if (format == null) {
format = detectFormat(file);
if (format == null) throw new IOException("invalid/unsupported mapping format");
}

if (format.hasNamespaces) {
try (Reader reader = Files.newBufferedReader(file)) {
return getNamespaces(reader, format);
/**
* Read mappings from a file or directory.
* @param path the file or directory to read from
* @param visitor the visitor receiving the mappings
*/
default void read(Path path, MappingVisitor visitor) throws IOException {
if (!path.toFile().isDirectory()) {
try (Reader reader = Files.newBufferedReader(path)) {
read(reader, path, visitor);
return;
}
} else {
return Arrays.asList(MappingUtil.NS_SOURCE_FALLBACK, MappingUtil.NS_TARGET_FALLBACK);
}
}

public static List<String> getNamespaces(Reader reader) throws IOException {
return getNamespaces(reader, null);
throw new UnsupportedOperationException("format doesn't support directories");
}

public static List<String> getNamespaces(Reader reader, MappingFormat format) throws IOException {
if (format == null) {
if (!reader.markSupported()) reader = new BufferedReader(reader);
reader.mark(DETECT_HEADER_LEN);
format = detectFormat(reader);
reader.reset();
if (format == null) throw new IOException("invalid/unsupported mapping format");
}

if (format.hasNamespaces) {
checkReaderCompatible(format);

switch (format) {
case TINY_FILE:
return Tiny1FileReader.getNamespaces(reader);
case TINY_2_FILE:
return Tiny2FileReader.getNamespaces(reader);
case TSRG_2_FILE:
return TsrgFileReader.getNamespaces(reader);
default:
throw new IllegalStateException();
}
} else {
return Arrays.asList(MappingUtil.NS_SOURCE_FALLBACK, MappingUtil.NS_TARGET_FALLBACK);
}
/**
* Read mappings from the reader if the format supports it, otherwise from the path.
* @param reader the reader to read from, given the format supports it
* @param path the file or directory to read from alternatively
* @param visitor the visitor receiving the mappings
* @throws IOException if an I/O error occurs or none of the given sources could be used
*/
void read(Reader reader, @Nullable Path path, MappingVisitor visitor) throws IOException;

default List<String> getNamespaces(Reader reader) throws IOException {
return Arrays.asList(MappingUtil.NS_SOURCE_FALLBACK, MappingUtil.NS_TARGET_FALLBACK);
}

public static void read(Path file, MappingVisitor visitor) throws IOException {
read(file, null, visitor);
}

public static void read(Path file, MappingFormat format, MappingVisitor visitor) throws IOException {
if (format == null) {
format = detectFormat(file);
if (format == null) throw new IOException("invalid/unsupported mapping format");
}

if (format.hasSingleFile()) {
try (Reader reader = Files.newBufferedReader(file)) {
read(reader, format, visitor);
}
} else {
switch (format) {
case ENIGMA_DIR:
EnigmaDirReader.read(file, visitor);
break;
default:
throw new IllegalStateException();
}
@ApiStatus.Internal
interface MappingFileReader extends MappingReader {
/**
* Read mappings from the passed reader.
* @param reader the reader to read from
* @param visitor the visitor receiving the mappings
* @throws IOException if an I/O error occurs
*/
default void read(Reader reader, MappingVisitor visitor) throws IOException {
read(reader, null, visitor);
}
}

public static void read(Reader reader, MappingVisitor visitor) throws IOException {
read(reader, null, visitor);
}

public static void read(Reader reader, MappingFormat format, MappingVisitor visitor) throws IOException {
if (format == null) {
if (!reader.markSupported()) reader = new BufferedReader(reader);
reader.mark(DETECT_HEADER_LEN);
format = detectFormat(reader);
reader.reset();
if (format == null) throw new IOException("invalid/unsupported mapping format");
}

checkReaderCompatible(format);

switch (format) {
case TINY_FILE:
Tiny1FileReader.read(reader, visitor);
break;
case TINY_2_FILE:
Tiny2FileReader.read(reader, visitor);
break;
case ENIGMA_FILE:
EnigmaFileReader.read(reader, visitor);
break;
case SRG_FILE:
SrgFileReader.read(reader, visitor);
break;
case TSRG_FILE:
case TSRG_2_FILE:
TsrgFileReader.read(reader, visitor);
break;
case PROGUARD_FILE:
ProGuardFileReader.read(reader, visitor);
break;
default:
throw new IllegalStateException();
@ApiStatus.Internal
interface MappingDirReader extends MappingReader {
@Override
default void read(Path dir, MappingVisitor visitor) throws IOException {
read(null, dir, visitor);
}
}

private static void checkReaderCompatible(MappingFormat format) throws IOException {
if (!format.hasSingleFile()) {
throw new IOException("can't read mapping format "+format.name+" using a Reader, use the Path based API");
}
@Override
void read(@Nullable Reader reader, @NotNull Path dir, MappingVisitor visitor) throws IOException;
}

private static final int DETECT_HEADER_LEN = 4096;
}
34 changes: 2 additions & 32 deletions src/main/java/net/fabricmc/mappingio/MappingWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,11 @@

import java.io.Closeable;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;

import net.fabricmc.mappingio.format.MappingFormat;
import net.fabricmc.mappingio.format.enigma.EnigmaDirWriter;
import net.fabricmc.mappingio.format.enigma.EnigmaFileWriter;
import net.fabricmc.mappingio.format.proguard.ProGuardFileWriter;
import net.fabricmc.mappingio.format.tiny.Tiny1FileWriter;
import net.fabricmc.mappingio.format.tiny.Tiny2FileWriter;
import org.jetbrains.annotations.ApiStatus;

@ApiStatus.NonExtendable
public interface MappingWriter extends Closeable, MappingVisitor {
static MappingWriter create(Path file, MappingFormat format) throws IOException {
if (format.hasSingleFile()) {
return create(Files.newBufferedWriter(file), format);
} else {
switch (format) {
case ENIGMA_DIR: return new EnigmaDirWriter(file, true);
default: throw new UnsupportedOperationException("format "+format+" is not implemented");
}
}
}

static MappingWriter create(Writer writer, MappingFormat format) throws IOException {
if (!format.hasSingleFile()) throw new IllegalArgumentException("format "+format+" is not applicable to a single writer");

switch (format) {
case TINY_FILE: return new Tiny1FileWriter(writer);
case TINY_2_FILE: return new Tiny2FileWriter(writer, false);
case ENIGMA_FILE: return new EnigmaFileWriter(writer);
case PROGUARD_FILE: return new ProGuardFileWriter(writer);
default: throw new UnsupportedOperationException("format "+format+" is not implemented");
}
}

@Override
default boolean visitEnd() throws IOException {
close();
Expand Down
Loading