Skip to content

Commit

Permalink
Fix: resolve correct input type when applying writeFixAndRead recursi…
Browse files Browse the repository at this point in the history
…vely

This type is used to encode the Typed structure to data, and matches the type that the fixer actually gets passed. Otherwise, we try to encode the sub-values with the old format, which fails.
  • Loading branch information
Gegy committed Jan 19, 2024
1 parent 77c1741 commit 070cfae
Showing 1 changed file with 17 additions and 6 deletions.
23 changes: 17 additions & 6 deletions src/main/java/com/mojang/datafixers/DataFix.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.BitSet;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;

public abstract class DataFix {
Expand Down Expand Up @@ -42,26 +43,32 @@ protected TypeRewriteRule writeAndRead(final String name, final Type<?> type, fi
return writeFixAndRead(name, type, newType, Function.identity());
}

@SuppressWarnings("unchecked")
protected <A, B> TypeRewriteRule writeFixAndRead(final String name, final Type<A> type, final Type<B> newType, final Function<Dynamic<?>, Dynamic<?>> fix) {
return fixTypeEverywhere(name, type, newType, ops -> input -> {
final Optional<? extends Dynamic<?>> written = type.writeDynamic(ops, input).resultOrPartial(LOGGER::error);
if (!written.isPresent()) {
final AtomicReference<Type<A>> patchedType = new AtomicReference<>();
final RewriteResult<A, B> view = unchecked(name, type, newType, ops -> input -> {
final Optional<? extends Dynamic<?>> written = patchedType.getPlain().writeDynamic(ops, input).resultOrPartial(LOGGER::error);
if (written.isEmpty()) {
throw new RuntimeException("Could not write the object in " + name);
}
final Optional<? extends Pair<Typed<B>, ?>> read = newType.readTyped(fix.apply(written.get())).resultOrPartial(LOGGER::error);
if (!read.isPresent()) {
if (read.isEmpty()) {
throw new RuntimeException("Could not read the new object in " + name);
}
return read.get().getFirst().getValue();
});
}, new BitSet());
final TypeRewriteRule rule = fixTypeEverywhere(type, view);
// Replace the input type within itself recursively, as this is what is actually passed to the fixer
patchedType.setPlain((Type<A>) type.all(rule, true, false).view().newType());
return rule;
}

protected <A, B> TypeRewriteRule fixTypeEverywhere(final String name, final Type<A> type, final Type<B> newType, final Function<DynamicOps<?>, Function<A, B>> function) {
return fixTypeEverywhere(name, type, newType, function, new BitSet());
}

protected <A, B> TypeRewriteRule fixTypeEverywhere(final String name, final Type<A> type, final Type<B> newType, final Function<DynamicOps<?>, Function<A, B>> function, final BitSet bitSet) {
return fixTypeEverywhere(type, RewriteResult.create(View.create(name, type, newType, new NamedFunctionWrapper<>(name, function)), bitSet));
return fixTypeEverywhere(type, unchecked(name, type, newType, function, bitSet));
}

protected <A> TypeRewriteRule fixTypeEverywhereTyped(final String name, final Type<A> type, final Function<Typed<?>, Typed<?>> function) {
Expand All @@ -80,6 +87,10 @@ protected <A, B> TypeRewriteRule fixTypeEverywhereTyped(final String name, final
return fixTypeEverywhere(type, checked(name, type, newType, function, bitSet));
}

private static <A, B> RewriteResult<A, B> unchecked(final String name, final Type<A> type, final Type<B> newType, final Function<DynamicOps<?>, Function<A, B>> function, final BitSet bitSet) {
return RewriteResult.create(View.create(name, type, newType, new NamedFunctionWrapper<>(name, function)), bitSet);
}

@SuppressWarnings("unchecked")
public static <A, B> RewriteResult<A, B> checked(final String name, final Type<A> type, final Type<B> newType, final Function<Typed<?>, Typed<?>> function, final BitSet bitSet) {
return RewriteResult.create(View.create(name, type, newType, new NamedFunctionWrapper<>(name, ops -> a -> {
Expand Down

0 comments on commit 070cfae

Please sign in to comment.