Skip to content

Commit

Permalink
Rework the mapping read and write APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
NebelNidas committed Oct 7, 2023
1 parent c646586 commit ab10550
Show file tree
Hide file tree
Showing 16 changed files with 322 additions and 229 deletions.
160 changes: 30 additions & 130 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,14 @@
import java.util.Arrays;
import java.util.List;

import org.jetbrains.annotations.ApiStatus;
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 +42,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 +82,32 @@ 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);
}
} 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);
}

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);
}
}

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();
/**
* 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;
}
}
}

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();
}
throw new UnsupportedOperationException("format doesn't support directories");
}

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");
}
/**
* 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);
}

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
39 changes: 39 additions & 0 deletions src/main/java/net/fabricmc/mappingio/format/MappingDirReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2023 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.mappingio.format;

import java.io.IOException;
import java.io.Reader;
import java.nio.file.Path;

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

import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.MappingVisitor;

@ApiStatus.Internal
public interface MappingDirReader extends MappingReader {
@Override
default void read(Path dir, MappingVisitor visitor) throws IOException {
read(null, dir, visitor);
}

@Override
void read(@Nullable Reader reader, @NotNull Path dir, MappingVisitor visitor) throws IOException;
}
38 changes: 38 additions & 0 deletions src/main/java/net/fabricmc/mappingio/format/MappingFileReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2023 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.mappingio.format;

import java.io.IOException;
import java.io.Reader;

import org.jetbrains.annotations.ApiStatus;

import net.fabricmc.mappingio.MappingReader;
import net.fabricmc.mappingio.MappingVisitor;

@ApiStatus.Internal
public 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);
}
}
Loading

0 comments on commit ab10550

Please sign in to comment.