Rework mutability of nodes

This commit is contained in:
Christopher Schnick 2021-12-18 03:19:18 +01:00
parent cf89b2ff18
commit 562f02b607
25 changed files with 503 additions and 208 deletions

View file

@ -99,7 +99,7 @@ public class DataTableImpl implements DataTable {
}, false);
}
}.execute();
return ArrayNode.wrap(nodes);
return ArrayNode.of(nodes);
}
@Override

View file

@ -20,6 +20,8 @@ dependencies {
compileOnly 'org.projectlombok:lombok:1.18.22'
annotationProcessor 'org.projectlombok:lombok:1.18.22'
testCompileOnly 'org.projectlombok:lombok:1.18.22'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.22'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'

View file

@ -1,5 +1,8 @@
package io.xpipe.core.data;
import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.TupleNode;
import io.xpipe.core.data.node.ValueNode;
import io.xpipe.core.data.type.DataType;
import java.util.Iterator;
@ -29,6 +32,10 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
throw unsupported("set raw data");
}
public DataStructureNode setNull() {
throw unsupported("set null");
}
public DataStructureNode set(int index, DataStructureNode node) {
throw unsupported("set at index");
}
@ -47,6 +54,34 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
return false;
}
public boolean isNull() {
throw unsupported("null check");
}
public final ValueNode asValue() {
if (!isValue()) {
throw new UnsupportedOperationException(getName() + " is not a value node");
}
return (ValueNode) this;
}
public final TupleNode asTuple() {
if (!isTuple()) {
throw new UnsupportedOperationException(getName() + " is not a tuple node");
}
return (TupleNode) this;
}
public final ArrayNode asArray() {
if (!isArray()) {
throw new UnsupportedOperationException(getName() + " is not an array node");
}
return (ArrayNode) this;
}
public DataStructureNode put(String keyName, DataStructureNode node) {
throw unsupported("put node with key");
}
@ -67,7 +102,7 @@ public abstract class DataStructureNode implements Iterable<DataStructureNode> {
throw unsupported("size computation");
}
public abstract DataType getDataType();
public abstract DataType determineDataType();
public DataStructureNode at(int index) {
throw unsupported("integer indexing");

View file

@ -92,7 +92,7 @@ public class GenericArrayReader implements GenericAbstractReader {
throw new IllegalStateException("Array ended but is not full yet");
}
created = ArrayNode.wrap(nodes);
created = ArrayNode.of(nodes);
}
@Override
@ -142,7 +142,7 @@ public class GenericArrayReader implements GenericAbstractReader {
throw new IllegalStateException("Array is full but got another value");
}
put(ValueNode.wrap(value));
put(ValueNode.mutable(value));
}
@Override
@ -156,6 +156,6 @@ public class GenericArrayReader implements GenericAbstractReader {
throw new IllegalStateException();
}
return ArrayNode.wrap(nodes);
return ArrayNode.of(nodes);
}
}

View file

@ -84,6 +84,6 @@ public class GenericDataStructureNodeReader implements GenericDataStreamCallback
return;
}
node = ValueNode.wrap(value);
node = ValueNode.mutable(value);
}
}

View file

@ -149,7 +149,7 @@ public class GenericTupleReader implements GenericAbstractReader {
throw new IllegalStateException("Tuple is full but got another value");
}
putNode(ValueNode.wrap(value));
putNode(ValueNode.mutable(value));
}
@Override

View file

@ -19,14 +19,14 @@ public class ArrayNode extends DataStructureNode {
}
public static ArrayNode of(DataStructureNode... dsn) {
return wrap(List.of(dsn));
return of(List.of(dsn));
}
public static ArrayNode wrap(List<DataStructureNode> valueNodes) {
public static ArrayNode of(List<DataStructureNode> valueNodes) {
return new ArrayNode(valueNodes);
}
public static ArrayNode copy(List<DataStructureNode> valueNodes) {
public static ArrayNode copyOf(List<DataStructureNode> valueNodes) {
return new ArrayNode(new ArrayList<>(valueNodes));
}
@ -69,8 +69,8 @@ public class ArrayNode extends DataStructureNode {
}
@Override
public ArrayType getDataType() {
return ArrayType.of(valueNodes.stream().map(DataStructureNode::getDataType).toList());
public ArrayType determineDataType() {
return ArrayType.of(valueNodes.stream().map(DataStructureNode::determineDataType).toList());
}
@Override

View file

@ -0,0 +1,26 @@
package io.xpipe.core.data.node;
import io.xpipe.core.data.DataStructureNode;
public class ImmutableValueNode extends ValueNode {
private final byte[] data;
ImmutableValueNode(byte[] data) {
this.data = data;
}
@Override
public String toString(int indent) {
return getClass().getSimpleName() + "(" + new String(data) + ")";
}
@Override
public DataStructureNode setRawData(byte[] data) {
throw new UnsupportedOperationException("Value node is immutable");
}
public byte[] getRawData() {
return data;
}
}

View file

@ -0,0 +1,27 @@
package io.xpipe.core.data.node;
import io.xpipe.core.data.DataStructureNode;
public class MutableValueNode extends ValueNode {
private byte[] data;
MutableValueNode(byte[] data) {
this.data = data;
}
@Override
public String toString(int indent) {
return getClass().getSimpleName() + "(" + new String(data) + ")";
}
@Override
public DataStructureNode setRawData(byte[] data) {
this.data = data;
return this;
}
public byte[] getRawData() {
return data;
}
}

View file

@ -17,8 +17,14 @@ public class NoKeyTupleNode extends TupleNode {
}
@Override
public DataType getDataType() {
return TupleType.wrap(null, nodes.stream().map(DataStructureNode::getDataType).toList());
public DataStructureNode set(int index, DataStructureNode node) {
nodes.set(index, node);
return this;
}
@Override
public DataType determineDataType() {
return TupleType.of(null, nodes.stream().map(DataStructureNode::determineDataType).toList());
}
@Override

View file

@ -19,8 +19,14 @@ public class SimpleTupleNode extends TupleNode {
}
@Override
public DataType getDataType() {
return TupleType.wrap(names, nodes.stream().map(DataStructureNode::getDataType).toList());
public DataStructureNode set(int index, DataStructureNode node) {
nodes.set(index, node);
return this;
}
@Override
public DataType determineDataType() {
return TupleType.of(names, nodes.stream().map(DataStructureNode::determineDataType).toList());
}
@Override
@ -50,6 +56,7 @@ public class SimpleTupleNode extends TupleNode {
@Override
public DataStructureNode clear() {
nodes.clear();
names.clear();
return this;
}

View file

@ -8,59 +8,68 @@ import lombok.EqualsAndHashCode;
import java.nio.charset.StandardCharsets;
@EqualsAndHashCode(callSuper = false)
public class ValueNode extends DataStructureNode {
public abstract class ValueNode extends DataStructureNode {
private byte[] data;
private static final byte[] NULL = new byte[] {0};
private ValueNode(byte[] data) {
this.data = data;
public static ValueNode immutable(byte[] data) {
return new ImmutableValueNode(data);
}
public static ValueNode wrap(byte[] data) {
return new ValueNode(data);
public static ValueNode mutableNull() {
return mutable(NULL);
}
public static ValueNode nullValue() {
return mutable(NULL);
}
public static ValueNode mutable(byte[] data) {
return new MutableValueNode(data);
}
public static ValueNode mutable(Object o) {
return mutable(o.toString().getBytes(StandardCharsets.UTF_8));
}
public static ValueNode of(byte[] data) {
return mutable(data);
}
public static ValueNode of(Object o) {
return new ValueNode(o.toString().getBytes(StandardCharsets.UTF_8));
return mutable(o);
}
protected ValueNode() {
}
@Override
public DataStructureNode setRawData(byte[] data) {
this.data = data;
return this;
}
public abstract DataStructureNode setRawData(byte[] data);
@Override
public boolean isValue() {
return true;
}
@Override
public int asInt() {
public final int asInt() {
return Integer.parseInt(asString());
}
@Override
public String asString() {
return new String(data);
public final String asString() {
return new String(getRawData());
}
@Override
protected String getName() {
public final boolean isValue() {
return true;
}
@Override
protected final String getName() {
return "value node";
}
@Override
public String toString(int indent) {
return new String(data);
public final DataType determineDataType() {
return ValueType.of();
}
@Override
public DataType getDataType() {
return new ValueType();
}
public byte[] getRawData() {
return data;
}
public abstract byte[] getRawData();
}

View file

@ -11,14 +11,18 @@ import java.util.List;
@EqualsAndHashCode
public class ArrayType implements DataType {
public static ArrayType ofWildcard() {
return new ArrayType(WildcardType.of());
}
public static ArrayType of(List<DataType> types) {
if (types.size() == 0) {
return new ArrayType(new WildcardType());
return new ArrayType(WildcardType.of());
}
var first = types.get(0);
var eq = types.stream().allMatch(d -> d.equals(first));
return new ArrayType(eq ? first : new WildcardType());
return new ArrayType(eq ? first : WildcardType.of());
}
private final DataType sharedType;

View file

@ -26,7 +26,7 @@ public class TupleType implements DataType {
return new TupleType(List.of(), List.of());
}
public static TupleType wrap(List<String> names, List<DataType> types) {
public static TupleType of(List<String> names, List<DataType> types) {
return new TupleType(names, types);
}

View file

@ -9,6 +9,14 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode
public class ValueType implements DataType {
public static ValueType of() {
return new ValueType();
}
private ValueType() {
}
@Override
public String getName() {
return "value";

View file

@ -5,6 +5,14 @@ import io.xpipe.core.data.type.callback.DataTypeCallback;
public class WildcardType implements DataType {
public static WildcardType of() {
return new WildcardType();
}
private WildcardType() {
}
@Override
public String getName() {
return "wildcard";

View file

@ -13,7 +13,7 @@ public interface DataTypeCallback {
return new DataTypeCallback() {
@Override
public void onValue() {
typeConsumer.accept(new ValueType());
typeConsumer.accept(ValueType.of());
}
@Override

View file

@ -50,7 +50,7 @@ public class TypedDataStreamWriter {
if (!type.getTypes().get(i).isWildcard()) {
write(out, tuple.at(i), type.getTypes().get(i));
} else {
GenericDataStreamWriter.write(out, tuple);
GenericDataStreamWriter.write(out, tuple.at(i));
}
}
}

View file

@ -11,25 +11,35 @@ import io.xpipe.core.data.type.callback.DataTypeCallback;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
public class TypedDataStructureNodeReader implements TypedAbstractReader {
public static TypedDataStructureNodeReader mutable(DataType type) {
return new TypedDataStructureNodeReader(type, false);
}
public static TypedDataStructureNodeReader immutable(DataType type) {
return new TypedDataStructureNodeReader(type, true);
}
private int currentDataTypeIndex;
private final List<DataType> flattened;
private Stack<List<DataStructureNode>> children;
private Stack<DataStructureNode> nodes;
private final Stack<List<DataStructureNode>> children;
private final Stack<DataStructureNode> nodes;
private DataStructureNode readNode;
private boolean initialized;
private int arrayDepth;
private boolean makeImmutable;
private final boolean makeImmutable;
public TypedDataStructureNodeReader(DataType type) {
private TypedDataStructureNodeReader(DataType type, boolean makeImmutable) {
flattened = new ArrayList<>();
children = new Stack<>();
nodes = new Stack<>();
type.traverseType(DataTypeCallback.flatten(d -> flattened.add(d)));
this.makeImmutable = makeImmutable;
}
@Override
@ -61,55 +71,22 @@ public class TypedDataStructureNodeReader implements TypedAbstractReader {
@Override
public void onValue(byte[] data) {
var val = makeImmutable ? ValueNode.immutable(data) : ValueNode.mutable(data);
if (!initialized) {
readNode = ValueNode.wrap(data);
readNode = val;
return;
}
children.peek().add(ValueNode.wrap(data));
children.peek().add(val);
if (!flattened.get(currentDataTypeIndex).isArray()) {
currentDataTypeIndex++;
}
}
private void finishTuple() {
children.pop();
var popped = nodes.pop();
if (!popped.isTuple()) {
throw new IllegalStateException();
}
SimpleTupleNode tuple = (SimpleTupleNode) popped;
if (tuple.getNames().size() != tuple.getNodes().size()) {
throw new IllegalStateException("");
}
if (nodes.empty()) {
readNode = popped;
} else {
children.peek().add(popped);
}
}
private boolean isInArray() {
return arrayDepth >= 1;
}
private void finishArray() {
arrayDepth--;
if (!isInArray()) {
currentDataTypeIndex++;
}
children.pop();
var popped = nodes.pop();
if (nodes.empty()) {
readNode = popped;
} else {
children.peek().add(popped);
}
}
@Override
public void onGenericNode(DataStructureNode node) {
children.peek().add(node);
@ -134,13 +111,32 @@ public class TypedDataStructureNodeReader implements TypedAbstractReader {
var l = new ArrayList<DataStructureNode>(tupleType.getSize());
children.push(l);
var newNode = TupleNode.wrapRaw(tupleType.getNames(), l);
var tupleNames = makeImmutable ?
Collections.unmodifiableList(tupleType.getNames()) : new ArrayList<>(tupleType.getNames());
var tupleNodes = makeImmutable ? Collections.unmodifiableList(l) : l;
var newNode = TupleNode.wrapRaw(tupleNames, tupleNodes);
nodes.push(newNode);
}
@Override
public void onTupleEnd() {
finishTuple();
children.pop();
var popped = nodes.pop();
if (!popped.isTuple()) {
throw new IllegalStateException();
}
SimpleTupleNode tuple = (SimpleTupleNode) popped;
if (tuple.getNames().size() != tuple.getNodes().size()) {
throw new IllegalStateException("");
}
if (nodes.empty()) {
readNode = popped;
} else {
children.peek().add(popped);
}
}
@Override
@ -151,13 +147,26 @@ public class TypedDataStructureNodeReader implements TypedAbstractReader {
var l = new ArrayList<DataStructureNode>();
children.push(l);
var newNode = ArrayNode.wrap(l);
var arrayNodes = makeImmutable ? Collections.unmodifiableList(l) : l;
var newNode = ArrayNode.of(arrayNodes);
nodes.push(newNode);
arrayDepth++;
}
@Override
public void onArrayEnd() {
finishArray();
arrayDepth--;
if (!isInArray()) {
currentDataTypeIndex++;
}
children.pop();
var popped = nodes.pop();
if (nodes.empty()) {
readNode = popped;
} else {
children.peek().add(popped);
}
}
}

View file

@ -11,7 +11,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class TypedReusableDataStructureNodeReader implements TypedDataStreamCallback {
public class TypedReusableDataStructureNodeReader implements TypedAbstractReader {
private TypedDataStructureNodeReader initialReader;
private DataStructureNode node;
@ -22,10 +22,15 @@ public class TypedReusableDataStructureNodeReader implements TypedDataStreamCall
public TypedReusableDataStructureNodeReader(DataType type) {
flattened = new ArrayList<>();
indices = new Stack<>();
initialReader = new TypedDataStructureNodeReader(type);
initialReader = TypedDataStructureNodeReader.mutable(type);
type.traverseType(DataTypeCallback.flatten(d -> flattened.add(d)));
}
@Override
public boolean isDone() {
return true;
}
public DataStructureNode create() {
return node;
}
@ -47,10 +52,12 @@ public class TypedReusableDataStructureNodeReader implements TypedDataStreamCall
}
if (isInArray()) {
getCurrentParent().set(indices.peek(), ValueNode.wrap(data));
indices.push(indices.pop() + 1);
getCurrentParent().set(indices.peek(), ValueNode.mutable(data));
} else {
getCurrent().setRawData(data);
}
if (!indices.isEmpty()) {
indices.push(indices.pop() + 1);
}
}
@ -62,11 +69,8 @@ public class TypedReusableDataStructureNodeReader implements TypedDataStreamCall
return;
}
if (isInArray()) {
getCurrentParent().set(indices.peek(), node);
indices.push(indices.pop() + 1);
} else {
getCurrent().set(indices.peek(), node);
getCurrentParent().set(indices.peek(), node);
if (!indices.isEmpty()) {
indices.push(indices.pop() + 1);
}
}
@ -140,7 +144,9 @@ public class TypedReusableDataStructureNodeReader implements TypedDataStreamCall
indices.pop();
arrayDepth--;
indices.push(indices.pop() + 1);
if (!indices.isEmpty()) {
indices.push(indices.pop() + 1);
}
}
@Override

View file

@ -1,22 +1,34 @@
package io.xpipe.core.test;
import io.xpipe.core.data.DataStructureNode;
import io.xpipe.core.data.generic.GenericDataStreamParser;
import io.xpipe.core.data.generic.GenericDataStreamWriter;
import io.xpipe.core.data.generic.GenericDataStructureNodeReader;
import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.TupleNode;
import io.xpipe.core.data.node.ValueNode;
import io.xpipe.core.data.typed.TypedDataStreamParser;
import io.xpipe.core.data.typed.TypedDataStreamWriter;
import io.xpipe.core.data.typed.TypedDataStructureNodeReader;
import io.xpipe.core.data.typed.TypedReusableDataStructureNodeReader;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class DataStructureTest {
public static DataStructureNode createTestData() {
var val = ValueNode.wrap("value".getBytes(StandardCharsets.UTF_8));
var flatArray = ArrayNode.wrap(List.of(ValueNode.of(1), ValueNode.of(2)));
var val = ValueNode.of("value");
var flatArray = ArrayNode.of(List.of(ValueNode.of(1), ValueNode.of(2)));
var flatTuple = TupleNode.builder().add("key1", val).build();
var nestedArray = ArrayNode.wrap(List.of(flatArray, flatTuple));
var nestedArray = ArrayNode.of(List.of(flatArray, flatTuple));
return TupleNode.builder()
.add("key1", val)
.add("key2", flatArray)
@ -53,4 +65,100 @@ public class DataStructureTest {
Assertions.assertEquals(key4.at(0), ArrayNode.of(ValueNode.of(1), ValueNode.of(2)));
Assertions.assertEquals(key4.at(0).at(0).asInt(), 1);
}
@ParameterizedTest
@EnumSource(DataStructureTests.TypedDataset.class)
public void testTypes(DataStructureTests.TypedDataset ds) throws IOException {
for (var el : ds.nodes) {
Assertions.assertTrue(ds.type.matches(el));
}
}
@ParameterizedTest
@EnumSource(DataStructureTests.TypedDataset.class)
public void testGenericIo(DataStructureTests.TypedDataset ds) throws IOException {
for (var el : ds.nodes) {
var dataOut = new ByteArrayOutputStream();
GenericDataStreamWriter.write(dataOut, el);
var data = dataOut.toByteArray();
var reader = new GenericDataStructureNodeReader();
GenericDataStreamParser.read(new ByteArrayInputStream(data), reader);
var readNode = reader.create();
Assertions.assertEquals(el, readNode);
}
}
@ParameterizedTest
@EnumSource(DataStructureTests.TypedDataset.class)
public void testMutableTypedIo(DataStructureTests.TypedDataset ds) throws IOException {
for (var node : ds.nodes) {
var dataOut = new ByteArrayOutputStream();
TypedDataStreamWriter.writeStructure(dataOut, node, ds.type);
var data = dataOut.toByteArray();
var reader = TypedDataStructureNodeReader.mutable(ds.type);
new TypedDataStreamParser(ds.type).readStructure(new ByteArrayInputStream(data), reader);
var readNode = reader.create();
Assertions.assertEquals(node, readNode);
Assertions.assertDoesNotThrow(() -> {
if (readNode.isTuple()) {
readNode.clear();
Assertions.assertEquals(readNode.size(), 0);
}
if (readNode.isArray()) {
readNode.clear();
Assertions.assertEquals(readNode.size(), 0);
}
});
}
}
@ParameterizedTest
@EnumSource(DataStructureTests.TypedDataset.class)
public void testImmutableTypedIo(DataStructureTests.TypedDataset ds) throws IOException {
for (var node : ds.nodes) {
var dataOut = new ByteArrayOutputStream();
TypedDataStreamWriter.writeStructure(dataOut, node, ds.type);
var data = dataOut.toByteArray();
var reader = TypedDataStructureNodeReader.immutable(ds.type);
new TypedDataStreamParser(ds.type).readStructure(new ByteArrayInputStream(data), reader);
var readNode = reader.create();
Assertions.assertEquals(node, readNode);
Assertions.assertThrows(UnsupportedOperationException.class, () -> {
if (readNode.isTuple() || readNode.isArray()) {
readNode.clear();
Assertions.assertEquals(readNode.size(), 0);
} else {
readNode.setRawData("abc".getBytes(StandardCharsets.UTF_8));
}
});
if (readNode.isTuple() || readNode.isArray()) {
Assertions.assertEquals(readNode.size(), node.size());
}
}
}
@ParameterizedTest
@EnumSource(DataStructureTests.TypedDataset.class)
public void testReusableTypedIo(DataStructureTests.TypedDataset ds) throws IOException {
var dataOut = new ByteArrayOutputStream();
for (var node : ds.nodes) {
TypedDataStreamWriter.writeStructure(dataOut, node, ds.type);
}
var data = dataOut.toByteArray();
var in = new ByteArrayInputStream(data);
var reader = new TypedReusableDataStructureNodeReader(ds.type);
for (var node : ds.nodes) {
new TypedDataStreamParser(ds.type).readStructure(in, reader);
var readNode = reader.create();
Assertions.assertEquals(node, readNode);
}
}
}

View file

@ -4,17 +4,47 @@ import io.xpipe.core.data.DataStructureNode;
import io.xpipe.core.data.node.ArrayNode;
import io.xpipe.core.data.node.TupleNode;
import io.xpipe.core.data.node.ValueNode;
import io.xpipe.core.data.type.*;
import lombok.AllArgsConstructor;
import java.nio.charset.StandardCharsets;
import java.util.List;
public class DataStructureTests {
public static DataStructureNode createTestData() {
var val = ValueNode.wrap("value".getBytes(StandardCharsets.UTF_8));
var flatArray = ArrayNode.wrap(List.of(ValueNode.of(1), ValueNode.of(2)));
@AllArgsConstructor
public static enum TypedDataset {
// Variety
DATA_1(createTestDataType1(), List.of(createTestData11(), createTestData12())),
// Multiple nested arrays
DATA_2(createTestDataType2(), List.of(createTestData21(), createTestData22())),
// Array with wildcard type
DATA_3(createTestData31().determineDataType(), List.of(createTestData31(), createTestData32())),
// Simple values
DATA_4(ValueType.of(), List.of(createTestData41(), createTestData42())),
// Array with wildcard type
DATA_5(createTestDataType5(), List.of(createTestData51(), createTestData52(), createTestData53())),
// Tuple with wildcard type
DATA_6(createTestDataType6(), List.of(createTestData61(), createTestData62()));
public DataType type;
public List<DataStructureNode> nodes;
}
private static DataStructureNode createTestData11() {
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
var flatArray = ArrayNode.of(List.of(ValueNode.of(1), ValueNode.of(2)));
var flatTuple = TupleNode.builder().add("key1", val).build();
var nestedArray = ArrayNode.wrap(List.of(flatArray, flatTuple));
var nestedArray = ArrayNode.of(List.of(flatArray, flatTuple));
return TupleNode.builder()
.add("key1", val)
.add("key2", flatArray)
@ -22,4 +52,109 @@ public class DataStructureTests {
.add("key4", nestedArray)
.build();
}
private static DataStructureNode createTestData12() {
var val = ValueNode.nullValue();
var flatArray = ArrayNode.of();
var flatTuple = TupleNode.builder().add("key1", val).build();
var nestedArray = ArrayNode.of(List.of(flatArray, flatTuple));
return TupleNode.builder()
.add("key1", val)
.add("key2", flatArray)
.add("key3", flatTuple)
.add("key4", nestedArray)
.build();
}
private static DataType createTestDataType1() {
return createTestData11().determineDataType();
}
public static DataStructureNode createTestData21() {
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
var flatArray = ArrayNode.of(List.of(ValueNode.of(1), ValueNode.of(2)));
var flatTuple = TupleNode.builder().add("key1", val).build();
var nestedArray = ArrayNode.of(List.of(flatArray, flatTuple));
var doubleNested = ArrayNode.of(val, flatArray, flatTuple, nestedArray);
return doubleNested;
}
public static DataStructureNode createTestData22() {
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
return ArrayNode.of(val);
}
public static DataType createTestDataType2() {
return ArrayType.ofWildcard();
}
public static DataStructureNode createTestData31() {
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
var flatTuple = TupleNode.builder().add("key1", val).build();
var flatArray = ArrayNode.of(List.of(val, flatTuple));
return flatArray;
}
public static DataStructureNode createTestData32() {
var val = ValueNode.of("value2".getBytes(StandardCharsets.UTF_8));
var flatTuple = TupleNode.builder().add("key1", ValueNode.nullValue()).add("key2", ValueNode.nullValue()).build();
var flatArray = ArrayNode.of(List.of(val, flatTuple));
return flatArray;
}
public static DataStructureNode createTestData41() {
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
return val;
}
public static DataStructureNode createTestData42() {
var val = ValueNode.nullValue();
return val;
}
public static DataStructureNode createTestData51() {
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
var flatArray = ArrayNode.of(List.of(val, ValueNode.nullValue()));
var array1 = ArrayNode.of(List.of(flatArray));
var array2 = ArrayNode.of(List.of(array1, array1));
return array2;
}
public static DataStructureNode createTestData52() {
var val = ValueNode.of("value2".getBytes(StandardCharsets.UTF_8));
var flatArray = ArrayNode.of(List.of(val));
return flatArray;
}
public static DataStructureNode createTestData53() {
var val = ValueNode.of("value2".getBytes(StandardCharsets.UTF_8));
var flatTuple = TupleNode.builder().add("key1", val).build();
var flatArray = ArrayNode.of(List.of(flatTuple, val));
return flatArray;
}
public static DataType createTestDataType5() {
return ArrayType.ofWildcard();
}
public static DataStructureNode createTestData61() {
var val = ValueNode.of("value".getBytes(StandardCharsets.UTF_8));
var array = ArrayNode.of(List.of(val, ValueNode.nullValue()));
var tuple = TupleNode.builder()
.add("key1", val).add("key2", array).build();
return tuple;
}
public static DataStructureNode createTestData62() {
var val = ValueNode.of("value2".getBytes(StandardCharsets.UTF_8));
var flatTuple = TupleNode.builder().add("key1", val).build();
var tuple = TupleNode.builder()
.add("key1", flatTuple).add("key2", val).build();
return tuple;
}
public static DataType createTestDataType6() {
return TupleType.of(List.of("key1", "key2"), List.of(WildcardType.of(), WildcardType.of()));
}
}

View file

@ -1,35 +0,0 @@
package io.xpipe.core.test;
import io.xpipe.core.data.generic.GenericDataStreamParser;
import io.xpipe.core.data.generic.GenericDataStreamWriter;
import io.xpipe.core.data.generic.GenericDataStructureNodeReader;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HexFormat;
import static io.xpipe.core.test.DataStructureTests.createTestData;
public class GenericDataStructureIoTest {
@Test
public void testBasicIo() throws IOException {
var obj = createTestData();
var dataOut = new ByteArrayOutputStream();
GenericDataStreamWriter.write(dataOut, obj);
var data = dataOut.toByteArray();
var format = HexFormat.of().withPrefix("0x").withDelimiter(" ");
System.out.println(format.formatHex(data));
var reader = new GenericDataStructureNodeReader();
GenericDataStreamParser.read(new ByteArrayInputStream(data), reader);
var node = reader.create();
Assertions.assertEquals(obj, node);
System.out.println(node);
}
}

View file

@ -1,61 +0,0 @@
package io.xpipe.core.test;
import io.xpipe.core.data.typed.TypedDataStreamParser;
import io.xpipe.core.data.typed.TypedDataStreamWriter;
import io.xpipe.core.data.typed.TypedDataStructureNodeReader;
import io.xpipe.core.data.typed.TypedReusableDataStructureNodeReader;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HexFormat;
import static io.xpipe.core.test.DataStructureTests.createTestData;
public class TypedDataStructureIoTest {
@Test
public void testBasicIo() throws IOException {
var obj = createTestData();
var type = obj.getDataType();
var dataOut = new ByteArrayOutputStream();
TypedDataStreamWriter.writeStructure(dataOut, obj, type);
var data = dataOut.toByteArray();
var format = HexFormat.of().withPrefix("0x").withDelimiter(" ");
System.out.println(format.formatHex(data));
var reader = new TypedDataStructureNodeReader(type);
new TypedDataStreamParser(type).readStructure(new ByteArrayInputStream(data), reader);
var node = reader.create();
Assertions.assertEquals(obj, node);
System.out.println(node);
}
@Test
public void testBasicReusableIo() throws IOException {
var obj = createTestData();
var type = obj.getDataType();
var dataOut = new ByteArrayOutputStream();
TypedDataStreamWriter.writeStructure(dataOut, obj, type);
TypedDataStreamWriter.writeStructure(dataOut, obj, type);
var data = dataOut.toByteArray();
var format = HexFormat.of().withPrefix("0x").withDelimiter(" ");
System.out.println(format.formatHex(data));
var in = new ByteArrayInputStream(data);
var reader = new TypedReusableDataStructureNodeReader(type);
new TypedDataStreamParser(type).readStructure(in, reader);
var firstNode = reader.create();
new TypedDataStreamParser(type).readStructure(in, reader);
var secondNode = reader.create();
System.out.println(firstNode);
Assertions.assertEquals(obj, firstNode);
Assertions.assertEquals(obj, secondNode);
}
}

View file

@ -4,4 +4,5 @@ module io.xpipe.core.test {
requires org.junit.jupiter.api;
requires org.junit.jupiter.params;
requires io.xpipe.core;
requires static lombok;
}