diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-03-22 18:25:49 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-03-22 18:25:49 +0000 |
| commit | 0a6b38ca7ee956cab5818c195856d5c159966f7a (patch) | |
| tree | 760bb0e88b5e83a2a44826ed032d580e334fd82a /src | |
| parent | ed1c39334aaf4635119532e9ba6098a46843321a (diff) | |
Serialize Patio data values to flatbuffers
Diffstat (limited to 'src')
4 files changed, 297 insertions, 98 deletions
diff --git a/src/main/java/org/shedlang/compiler/patio/serialization/PatioToFlatbuffers.java b/src/main/java/org/shedlang/compiler/patio/serialization/PatioToFlatbuffers.java index 6e5545a5..7eaae88e 100644 --- a/src/main/java/org/shedlang/compiler/patio/serialization/PatioToFlatbuffers.java +++ b/src/main/java/org/shedlang/compiler/patio/serialization/PatioToFlatbuffers.java @@ -323,6 +323,177 @@ public class PatioToFlatbuffers { }; } + // == Data values == + + public static int serializeDataValue(FlatBufferBuilder builder, PatioDataValue value) { + return switch (value) { + case PatioDataValueArray array -> { + var elementLayoutFbs = serializeDataLayout(builder, array.elementLayout()); + + var elementsOffsetsFbs = array.elements().stream() + .mapToInt(element -> serializeDataValue(builder, element)) + .toArray(); + var elementsVectorFbs = PatioDataValueArrayFbs.createElementsVector(builder, elementsOffsetsFbs); + + PatioDataValueArrayFbs.startPatioDataValueArrayFbs(builder); + PatioDataValueArrayFbs.addElementLayout(builder, elementLayoutFbs); + PatioDataValueArrayFbs.addElements(builder, elementsVectorFbs); + var arrayFbs = PatioDataValueArrayFbs.endPatioDataValueArrayFbs(builder); + + PatioDataValueFbs.startPatioDataValueFbs(builder); + PatioDataValueFbs.addValueType(builder, PatioDataValueValueFbs.PatioDataValueArrayFbs); + PatioDataValueFbs.addValue(builder, arrayFbs); + yield PatioDataValueFbs.endPatioDataValueFbs(builder); + } + + case PatioDataValueBool bool -> { + PatioDataValueBoolFbs.startPatioDataValueBoolFbs(builder); + PatioDataValueBoolFbs.addValue(builder, bool.value()); + var boolFbs = PatioDataValueBoolFbs.endPatioDataValueBoolFbs(builder); + + PatioDataValueFbs.startPatioDataValueFbs(builder); + PatioDataValueFbs.addValueType(builder, PatioDataValueValueFbs.PatioDataValueBoolFbs); + PatioDataValueFbs.addValue(builder, boolFbs); + yield PatioDataValueFbs.endPatioDataValueFbs(builder); + } + + case PatioDataValueByte byte_ -> { + PatioDataValueByteFbs.startPatioDataValueByteFbs(builder); + PatioDataValueByteFbs.addValue(builder, byte_.value()); + var byteFbs = PatioDataValueByteFbs.endPatioDataValueByteFbs(builder); + + PatioDataValueFbs.startPatioDataValueFbs(builder); + PatioDataValueFbs.addValueType(builder, PatioDataValueValueFbs.PatioDataValueByteFbs); + PatioDataValueFbs.addValue(builder, byteFbs); + yield PatioDataValueFbs.endPatioDataValueFbs(builder); + } + + case PatioDataValueDataPtr dataPtr -> { + var dataPtrValueFbs = serializeDataPtrValue(builder, dataPtr.value()); + + PatioDataValueDataPtrFbs.startPatioDataValueDataPtrFbs(builder); + PatioDataValueDataPtrFbs.addValue(builder, dataPtrValueFbs); + var dataPtrFbs = PatioDataValueDataPtrFbs.endPatioDataValueDataPtrFbs(builder); + + PatioDataValueFbs.startPatioDataValueFbs(builder); + PatioDataValueFbs.addValueType(builder, PatioDataValueValueFbs.PatioDataValueDataPtrFbs); + PatioDataValueFbs.addValue(builder, dataPtrFbs); + yield PatioDataValueFbs.endPatioDataValueFbs(builder); + } + + case PatioDataValueInt int_ -> { + var intValueFbs = serializeIntValue(builder, int_.value()); + + PatioDataValueIntFbs.startPatioDataValueIntFbs(builder); + PatioDataValueIntFbs.addValue(builder, intValueFbs); + var intFbs = PatioDataValueIntFbs.endPatioDataValueIntFbs(builder); + + PatioDataValueFbs.startPatioDataValueFbs(builder); + PatioDataValueFbs.addValueType(builder, PatioDataValueValueFbs.PatioDataValueIntFbs); + PatioDataValueFbs.addValue(builder, intFbs); + yield PatioDataValueFbs.endPatioDataValueFbs(builder); + } + + case PatioDataValueInt32 int32 -> { + var intValueFbs = serializeIntValue(builder, int32.value()); + + PatioDataValueInt32Fbs.startPatioDataValueInt32Fbs(builder); + PatioDataValueInt32Fbs.addValue(builder, intValueFbs); + var int32Fbs = PatioDataValueInt32Fbs.endPatioDataValueInt32Fbs(builder); + + PatioDataValueFbs.startPatioDataValueFbs(builder); + PatioDataValueFbs.addValueType(builder, PatioDataValueValueFbs.PatioDataValueInt32Fbs); + PatioDataValueFbs.addValue(builder, int32Fbs); + yield PatioDataValueFbs.endPatioDataValueFbs(builder); + } + + case PatioDataValueStruct struct -> { + var elementsOffsetsFbs = struct.elements().stream() + .mapToInt(element -> serializeDataValue(builder, element)) + .toArray(); + var elementsVectorFbs = PatioDataValueStructFbs.createElementsVector(builder, elementsOffsetsFbs); + + PatioDataValueStructFbs.startPatioDataValueStructFbs(builder); + PatioDataValueStructFbs.addElements(builder, elementsVectorFbs); + var structFbs = PatioDataValueStructFbs.endPatioDataValueStructFbs(builder); + + PatioDataValueFbs.startPatioDataValueFbs(builder); + PatioDataValueFbs.addValueType(builder, PatioDataValueValueFbs.PatioDataValueStructFbs); + PatioDataValueFbs.addValue(builder, structFbs); + yield PatioDataValueFbs.endPatioDataValueFbs(builder); + } + }; + } + + public static PatioDataValue deserializeDataValue(PatioDataValueFbs valueFbs) { + return switch (valueFbs.valueType()) { + case PatioDataValueValueFbs.PatioDataValueArrayFbs -> { + var arrayFbs = (PatioDataValueArrayFbs) valueFbs.value(new PatioDataValueArrayFbs()); + + var elementLayout = deserializeDataLayout(arrayFbs.elementLayout()); + + var elements = mapVector( + arrayFbs::elements, + arrayFbs.elementsLength(), + PatioToFlatbuffers::deserializeDataValue + ); + + yield new PatioDataValueArray(elementLayout, elements); + } + + case PatioDataValueValueFbs.PatioDataValueBoolFbs -> { + var boolFbs = (PatioDataValueBoolFbs) valueFbs.value(new PatioDataValueBoolFbs()); + + yield new PatioDataValueBool(boolFbs.value()); + } + + case PatioDataValueValueFbs.PatioDataValueByteFbs -> { + var byteFbs = (PatioDataValueByteFbs) valueFbs.value(new PatioDataValueByteFbs()); + + yield new PatioDataValueByte((byte) byteFbs.value()); + } + + case PatioDataValueValueFbs.PatioDataValueDataPtrFbs -> { + var dataPtrFbs = (PatioDataValueDataPtrFbs) valueFbs.value(new PatioDataValueDataPtrFbs()); + + var value = deserializeDataPtrValue(dataPtrFbs.value()); + + yield new PatioDataValueDataPtr(value); + } + + case PatioDataValueValueFbs.PatioDataValueIntFbs -> { + var intFbs = (PatioDataValueIntFbs) valueFbs.value(new PatioDataValueIntFbs()); + + var value = deserializeIntValue(intFbs.value()); + + yield new PatioDataValueInt(value); + } + + case PatioDataValueValueFbs.PatioDataValueInt32Fbs -> { + var int32Fbs = (PatioDataValueInt32Fbs) valueFbs.value(new PatioDataValueInt32Fbs()); + + var value = deserializeIntValue(int32Fbs.value()); + + yield new PatioDataValueInt32(value); + } + + case PatioDataValueValueFbs.PatioDataValueStructFbs -> { + var structFbs = (PatioDataValueStructFbs) valueFbs.value(new PatioDataValueStructFbs()); + + var elements = mapVector( + structFbs::elements, + structFbs.elementsLength(), + PatioToFlatbuffers::deserializeDataValue + ); + + yield new PatioDataValueStruct(elements); + } + + default -> + throw new UnsupportedOperationException("TODO"); + }; + } + // == Flatbuffers == private static <T, R> List<R> mapVector(Function<Integer, T> get, int length, Function<T, R> map) { diff --git a/src/test/java/org/shedlang/compiler/patio/serialization/PatioSerializationTests.java b/src/test/java/org/shedlang/compiler/patio/serialization/PatioSerializationTests.java index 791743c0..14d47932 100644 --- a/src/test/java/org/shedlang/compiler/patio/serialization/PatioSerializationTests.java +++ b/src/test/java/org/shedlang/compiler/patio/serialization/PatioSerializationTests.java @@ -2,10 +2,7 @@ package org.shedlang.compiler.patio.serialization; import org.junit.jupiter.api.Test; import org.shedlang.compiler.patio.instructions.Patio; -import org.shedlang.compiler.patio.types.PatioDataLayout; -import org.shedlang.compiler.patio.types.PatioDataLayouts; -import org.shedlang.compiler.patio.types.PatioType; -import org.shedlang.compiler.patio.types.PatioTypes; +import org.shedlang.compiler.patio.types.*; import org.shedlang.compiler.patio.values.PatioDataPtrValue; import org.shedlang.compiler.patio.values.PatioIntValue; @@ -265,4 +262,98 @@ public abstract class PatioSerializationTests { assertThat(deserializedLayout, equalTo(layout)); } + + // == Data values == + + protected abstract PatioDataValue deserializeDataValue(byte[] buffer); + protected abstract byte[] serializeDataValue(PatioDataValue value); + + + @Test + public void canSerializeDataValueArray() { + var value = PatioDataValues.array( + PatioDataLayouts.BYTE, + List.of( + PatioDataValues.byte_(0x01), + PatioDataValues.byte_(0x02), + PatioDataValues.byte_(0x03) + ) + ); + + var deserializedValue = deserializeDataValue( + serializeDataValue(value) + ); + + assertThat(deserializedValue, equalTo(value)); + } + + @Test + public void canSerializeDataValueBool() { + var value = PatioDataValues.bool(true); + + var deserializedValue = deserializeDataValue( + serializeDataValue(value) + ); + + assertThat(deserializedValue, equalTo(value)); + } + + @Test + public void canSerializeDataValueByte() { + var value = PatioDataValues.byte_(0xc8); + + var deserializedValue = deserializeDataValue( + serializeDataValue(value) + ); + + assertThat(deserializedValue, equalTo(value)); + } + + @Test + public void canSerializeDataValueDataPtr() { + var value = PatioDataValues.dataPtrNull(); + + var deserializedValue = deserializeDataValue( + serializeDataValue(value) + ); + + assertThat(deserializedValue, equalTo(value)); + } + + @Test + public void canSerializeDataValueInt() { + var value = PatioDataValues.int_(42); + + var deserializedValue = deserializeDataValue( + serializeDataValue(value) + ); + + assertThat(deserializedValue, equalTo(value)); + } + + @Test + public void canSerializeDataValueInt32() { + var value = PatioDataValues.int32(42); + + var deserializedValue = deserializeDataValue( + serializeDataValue(value) + ); + + assertThat(deserializedValue, equalTo(value)); + } + + @Test + public void canSerializeDataValueStruct() { + var value = PatioDataValues.struct(List.of( + PatioDataValues.byte_(0x01), + PatioDataValues.byte_(0x02), + PatioDataValues.byte_(0x03) + )); + + var deserializedValue = deserializeDataValue( + serializeDataValue(value) + ); + + assertThat(deserializedValue, equalTo(value)); + } } diff --git a/src/test/java/org/shedlang/compiler/patio/serialization/PatioToFlatbuffersTests.java b/src/test/java/org/shedlang/compiler/patio/serialization/PatioToFlatbuffersTests.java index 2f6fdede..e8c5eaa8 100644 --- a/src/test/java/org/shedlang/compiler/patio/serialization/PatioToFlatbuffersTests.java +++ b/src/test/java/org/shedlang/compiler/patio/serialization/PatioToFlatbuffersTests.java @@ -1,11 +1,9 @@ package org.shedlang.compiler.patio.serialization; import com.google.flatbuffers.FlatBufferBuilder; -import org.shedlang.compiler.patio.flatbuffers.PatioDataLayoutFbs; -import org.shedlang.compiler.patio.flatbuffers.PatioDataPtrValueFbs; -import org.shedlang.compiler.patio.flatbuffers.PatioIntValueFbs; -import org.shedlang.compiler.patio.flatbuffers.PatioTypeFbs; +import org.shedlang.compiler.patio.flatbuffers.*; import org.shedlang.compiler.patio.types.PatioDataLayout; +import org.shedlang.compiler.patio.types.PatioDataValue; import org.shedlang.compiler.patio.types.PatioType; import org.shedlang.compiler.patio.values.PatioDataPtrValue; import org.shedlang.compiler.patio.values.PatioIntValue; @@ -68,4 +66,18 @@ public class PatioToFlatbuffersTests extends PatioSerializationTests { var valueFbs = PatioDataLayoutFbs.getRootAsPatioDataLayoutFbs(ByteBuffer.wrap(buffer)); return PatioToFlatbuffers.deserializeDataLayout(valueFbs); } + + @Override + protected byte[] serializeDataValue(PatioDataValue value) { + var builder = new FlatBufferBuilder(); + var valueFbs = PatioToFlatbuffers.serializeDataValue(builder, value); + builder.finish(valueFbs); + return builder.sizedByteArray(); + } + + @Override + protected PatioDataValue deserializeDataValue(byte[] buffer) { + var valueFbs = PatioDataValueFbs.getRootAsPatioDataValueFbs(ByteBuffer.wrap(buffer)); + return PatioToFlatbuffers.deserializeDataValue(valueFbs); + } } diff --git a/src/test/java/org/shedlang/compiler/patio/serialization/PatioToProtobufTests.java b/src/test/java/org/shedlang/compiler/patio/serialization/PatioToProtobufTests.java index 44334435..a57b7810 100644 --- a/src/test/java/org/shedlang/compiler/patio/serialization/PatioToProtobufTests.java +++ b/src/test/java/org/shedlang/compiler/patio/serialization/PatioToProtobufTests.java @@ -79,6 +79,21 @@ public class PatioToProtobufTests extends PatioSerializationTests { } } + @Override + protected byte[] serializeDataValue(PatioDataValue value) { + return PatioToProtobuf.serializeDataValue(value).toByteArray(); + } + + @Override + protected PatioDataValue deserializeDataValue(byte[] buffer) { + try { + var valueProtobuf = PatioProtobuf.PatioDataValue.parseFrom(buffer); + return PatioToProtobuf.deserializeDataValue(valueProtobuf); + } catch (InvalidProtocolBufferException exception) { + throw new RuntimeException(exception); + } + } + // == Compilation unit == @Test @@ -780,94 +795,4 @@ public class PatioToProtobufTests extends PatioSerializationTests { assertThat(deserializedOperand, equalTo(operand)); } - - // == Data values == - - @Test - public void canSerializeDataValueArray() { - var value = PatioDataValues.array( - PatioDataLayouts.BYTE, - List.of( - PatioDataValues.byte_(0x01), - PatioDataValues.byte_(0x02), - PatioDataValues.byte_(0x03) - ) - ); - - var deserializedValue = PatioToProtobuf.deserializeDataValue( - PatioToProtobuf.serializeDataValue(value) - ); - - assertThat(deserializedValue, equalTo(value)); - } - - @Test - public void canSerializeDataValueBool() { - var value = PatioDataValues.bool(true); - - var deserializedValue = PatioToProtobuf.deserializeDataValue( - PatioToProtobuf.serializeDataValue(value) - ); - - assertThat(deserializedValue, equalTo(value)); - } - - @Test - public void canSerializeDataValueByte() { - var value = PatioDataValues.byte_(0xc8); - - var deserializedValue = PatioToProtobuf.deserializeDataValue( - PatioToProtobuf.serializeDataValue(value) - ); - - assertThat(deserializedValue, equalTo(value)); - } - - @Test - public void canSerializeDataValueDataPtr() { - var value = PatioDataValues.dataPtrNull(); - - var deserializedValue = PatioToProtobuf.deserializeDataValue( - PatioToProtobuf.serializeDataValue(value) - ); - - assertThat(deserializedValue, equalTo(value)); - } - - @Test - public void canSerializeDataValueInt() { - var value = PatioDataValues.int_(42); - - var deserializedValue = PatioToProtobuf.deserializeDataValue( - PatioToProtobuf.serializeDataValue(value) - ); - - assertThat(deserializedValue, equalTo(value)); - } - - @Test - public void canSerializeDataValueInt32() { - var value = PatioDataValues.int32(42); - - var deserializedValue = PatioToProtobuf.deserializeDataValue( - PatioToProtobuf.serializeDataValue(value) - ); - - assertThat(deserializedValue, equalTo(value)); - } - - @Test - public void canSerializeDataValueStruct() { - var value = PatioDataValues.struct(List.of( - PatioDataValues.byte_(0x01), - PatioDataValues.byte_(0x02), - PatioDataValues.byte_(0x03) - )); - - var deserializedValue = PatioToProtobuf.deserializeDataValue( - PatioToProtobuf.serializeDataValue(value) - ); - - assertThat(deserializedValue, equalTo(value)); - } } |
