Skip to content
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
26 changes: 19 additions & 7 deletions dfu/src/main/java/org/enginehub/linbus/dfu/LinOps.java
Original file line number Diff line number Diff line change
Expand Up @@ -462,10 +462,26 @@ private static void addHomogenized(
return;
}
for (LinTag<?> element : elements) {
builder.add(element instanceof LinCompoundTag existing ? existing : wrapElement(element));
builder.add(wrapElementIfNeeded(element));
}
}

private static LinCompoundTag wrapElementIfNeeded(LinTag<?> element) {
// If the element is a compound that isn't already wrapper-looking, we can use it as-is.
// Otherwise, we need to wrap it again to preserve the value when unwrapped later.
if (element instanceof LinCompoundTag compound && unwrapOrNull(compound) == null) {
return compound;
}
return LinCompoundTag.of(Map.of("", element));
}

private static @Nullable LinTag<?> unwrapOrNull(LinCompoundTag compound) {
if (compound.value().size() == 1) {
return compound.value().get("");
}
return null;
}

/**
* {@return the shared type of {@code elements}, or the compound type if they are heterogeneous}
*
Expand Down Expand Up @@ -510,13 +526,9 @@ private static List<LinTag<?>> unwrapStoredList(LinListTag<?> list) {
return result;
}

private static LinCompoundTag wrapElement(LinTag<?> element) {
return LinCompoundTag.of(Map.of("", element));
}

private static LinTag<?> tryUnwrap(LinTag<?> element) {
if (element instanceof LinCompoundTag compound && compound.value().size() == 1) {
LinTag<?> unwrapped = compound.value().get("");
if (element instanceof LinCompoundTag compound) {
LinTag<?> unwrapped = unwrapOrNull(compound);
if (unwrapped != null) {
return unwrapped;
}
Expand Down
47 changes: 47 additions & 0 deletions dfu/src/test/java/org/enginehub/linbus/dfu/LinOpsListTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,39 @@ void createListWrapsOnlyNonCompoundElementsWhenMixedWithCompound() {
assertThat(OPS.getStream(list)).hasStreamResultThat().containsExactly(a, LinIntTag.of(2)).inOrder();
}

@Test
@NbtOpsBehavior
void createListWrapsWrapperShapedCompoundElements() {
LinCompoundTag wrapperShaped = wrap(LinIntTag.of(1));
LinCompoundTag other = LinCompoundTag.builder().putInt("a", 1).build();
LinTag<?> list = OPS.createList(Stream.of(wrapperShaped, other));
assertThat(list)
.isEqualTo(LinListTag.of(LinTagType.compoundTag(), List.of(wrap(wrapperShaped), other)));
assertThat(OPS.getStream(list))
.hasStreamResultThat().containsExactly(wrapperShaped, other).inOrder();
}

@Test
@NbtOpsBehavior
void createListWrapsWrapperShapedCompoundElementsAlone() {
LinCompoundTag wrapperShaped = wrap(LinIntTag.of(1));
LinTag<?> list = OPS.createList(Stream.of(wrapperShaped));
assertThat(list)
.isEqualTo(LinListTag.of(LinTagType.compoundTag(), List.of(wrap(wrapperShaped))));
assertThat(OPS.getStream(list))
.hasStreamResultThat().containsExactly(wrapperShaped).inOrder();
}

@Test
@NbtOpsBehavior
void createListOfOnlyWrapperShapedCompoundsRoundTrips() {
LinCompoundTag a = wrap(LinIntTag.of(1));
LinCompoundTag b = wrap(LinStringTag.of("x"));
LinTag<?> list = OPS.createList(Stream.of(a, b));
assertThat(list).isEqualTo(LinListTag.of(LinTagType.compoundTag(), List.of(wrap(a), wrap(b))));
assertThat(OPS.getStream(list)).hasStreamResultThat().containsExactly(a, b).inOrder();
}

@Test
void mergeToListOntoEndTakesElementType() {
assertThat(OPS.mergeToList(LinEndTag.instance(), LinIntTag.of(1)))
Expand Down Expand Up @@ -157,6 +190,20 @@ void mergeToListGrowsWrappedList() {
)));
}

@Test
@NbtOpsBehavior
void mergeToListWrapsWrapperShapedCompound() {
LinCompoundTag wrapperShaped = wrap(LinIntTag.of(2));
LinTag<?> list = OPS.mergeToList(
LinListTag.of(LinTagType.intTag(), List.of(LinIntTag.of(1))), wrapperShaped
).result().orElseThrow();
assertThat(list).isEqualTo(LinListTag.of(LinTagType.compoundTag(), List.of(
wrap(LinIntTag.of(1)), wrap(wrapperShaped)
)));
assertThat(OPS.getStream(list))
.hasStreamResultThat().containsExactly(LinIntTag.of(1), wrapperShaped).inOrder();
}

@Test
void mergeToListAppendsSeveralValues() {
assertThat(OPS.mergeToList(
Expand Down