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

Add some helpful transform methods #13

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
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")
)
)
)
);
}
}
Loading