Skip to content

Commit

Permalink
Add some helpful transform methods
Browse files Browse the repository at this point in the history
Fixes #12
  • Loading branch information
octylFractal committed Oct 26, 2024
1 parent 2c109ba commit 81afdcf
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 0 deletions.
49 changes: 49 additions & 0 deletions tree/src/main/java/org/enginehub/linbus/tree/LinCompoundTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.Function;

/**
* Represents a compound tag.
Expand Down Expand Up @@ -395,6 +396,54 @@ public <T extends LinTag<?>> LinListTag<T> getListTag(
return cast;
}

private LinCompoundTag withChangedTag(String name, LinTag<?> value) {
LinkedHashMap<String, LinTag<?>> newMap = new LinkedHashMap<>(this.value);
newMap.put(name, value);
return new LinCompoundTag(Collections.unmodifiableMap(newMap), false);
}

/**
* Transform a value in the compound tag. You may change the type of the tag.
*
* <p>
* This uses {@link #getTag(String, LinTagType)}, so it will throw an exception if the tag does not exist
* or is of the wrong type.
* </p>
*
* @param name the name of the tag to transform
* @param type the type of the tag to transform
* @param transformer the function to transform the tag
* @return the new compound tag
*/
public <T extends LinTag<?>> LinCompoundTag transformTag(
String name, LinTagType<T> type, Function<T, ? extends LinTag<?>> transformer
) {
T tag = getTag(name, type);
LinTag<?> transformed = transformer.apply(tag);
return withChangedTag(name, transformed);
}

/**
* Transform a list value in the compound tag. You may change the type of the tag.
*
* <p>
* This uses {@link #getListTag(String, LinTagType)}, so it will throw an exception if the tag does not exist
* or is of the wrong type.
* </p>
*
* @param name the name of the tag to transform
* @param elementType the element type of the list tag to transform
* @param transformer the function to transform the tag
* @return the new compound tag
*/
public <T extends LinTag<?>> LinCompoundTag transformListTag(
String name, LinTagType<T> elementType, Function<LinListTag<T>, ? extends LinTag<?>> transformer
) {
LinListTag<T> tag = getListTag(name, elementType);
LinTag<?> transform = transformer.apply(tag);
return withChangedTag(name, transform);
}

/**
* Converts this tag into a {@link Builder}.
*
Expand Down
14 changes: 14 additions & 0 deletions tree/src/main/java/org/enginehub/linbus/tree/LinListTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

/**
* Represents a list of {@link LinTag LinTags}.
Expand Down Expand Up @@ -219,6 +220,19 @@ public T get(int index) {
return value.get(index);
}

/**
* Transform the tag at the given index.
*
* @param index the index of the tag to transform
* @param transformer the function to transform the tag
* @return the new list tag
*/
public LinListTag<T> transformTag(int index, Function<T, T> transformer) {
var newValue = new ArrayList<>(value);
newValue.set(index, transformer.apply(value.get(index)));
return new LinListTag<>(elementType, List.copyOf(newValue));
}

/**
* Converts this tag into a {@link Builder}.
*
Expand Down
21 changes: 21 additions & 0 deletions tree/src/main/java/org/enginehub/linbus/tree/LinRootEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import java.io.UncheckedIOException;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

/**
* Represents the root implicit-compound-tag entry.
Expand Down Expand Up @@ -65,6 +66,26 @@ public static LinRootEntry readFrom(LinStream tokens) throws IOException {
Objects.requireNonNull(value);
}

/**
* Transform the name of this entry.
*
* @param nameTransformer the function to transform the name
* @return the new entry
*/
public LinRootEntry transformName(Function<String, String> nameTransformer) {
return new LinRootEntry(nameTransformer.apply(name), value);
}

/**
* Transform the value of this entry.
*
* @param valueTransformer the function to transform the value
* @return the new entry
*/
public LinRootEntry transformValue(Function<LinCompoundTag, LinCompoundTag> valueTransformer) {
return new LinRootEntry(name, valueTransformer.apply(value));
}

/**
* Write this entry to a byte array.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,25 @@ void getByName() {
}
}

@Test
void transformByName() {
var tag = LinCompoundTag.of(new LinkedHashMap<>() {{
put("Hello", LinStringTag.of("World!"));
put("Goodbye", LinIntArrayTag.of(0xCAFE, 0xBABE));
}});
var transformed = tag.transformTag("Hello", LinTagType.stringTag(), t -> LinStringTag.of("New World!"));
assertThat(transformed).isEqualTo(LinCompoundTag.of(new LinkedHashMap<>() {{
put("Hello", LinStringTag.of("New World!"));
put("Goodbye", LinIntArrayTag.of(0xCAFE, 0xBABE));
}}));

var transformedToNewType = tag.transformTag("Hello", LinTagType.stringTag(), t -> LinIntArrayTag.of(0xDEAD, 0xBEEF));
assertThat(transformedToNewType).isEqualTo(LinCompoundTag.of(new LinkedHashMap<>() {{
put("Hello", LinIntArrayTag.of(0xDEAD, 0xBEEF));
put("Goodbye", LinIntArrayTag.of(0xCAFE, 0xBABE));
}}));
}

@Test
void findByName() {
var tag = LinCompoundTag.of(new LinkedHashMap<>() {{
Expand Down
14 changes: 14 additions & 0 deletions tree/src/test/java/org/enginehub/linbus/tree/LinListTagTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ void setOnBuilder() {
).isEqualTo(initial.toBuilder().set(0, LinStringTag.of("Goodbye...")).build());
}

@Test
void transformByIndex() {
var initial = LinListTag.of(LinTagType.stringTag(), List.of(
LinStringTag.of("Hello"),
LinStringTag.of("World!")
));
assertThat(
LinListTag.of(LinTagType.stringTag(), List.of(
LinStringTag.of("Hello"),
LinStringTag.of("Goodbye...")
))
).isEqualTo(initial.transformTag(1, s -> LinStringTag.of("Goodbye...")));
}

@Test
void emptyImplementation() {
var empty = LinListTag.empty(LinTagType.stringTag());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.enginehub.linbus.tree;

import org.junit.jupiter.api.Test;

public class NestedTransformShowcaseTest {
@Test
void transformSchematicMetadata() {
LinRootEntry root = new LinRootEntry(
"",
LinCompoundTag.builder()
.put("Schematic", LinCompoundTag.builder()
.put("Metadata", LinCompoundTag.builder()
.put("Name", LinStringTag.of("My Schematic"))
.put("Author", LinStringTag.of("Linbus"))
.build())
.build())
.build()
);
LinRootEntry withNewName = root.transformValue(v ->
v.transformTag("Schematic", LinTagType.compoundTag(), schematic ->
schematic.transformTag("Metadata", LinTagType.compoundTag(), metadata ->
metadata.transformTag("Name", LinTagType.stringTag(), name ->
LinStringTag.of("My New Schematic")
)
)
)
);
}
}

0 comments on commit 81afdcf

Please sign in to comment.