--- /dev/null
+package org.simantics.databoard.streaming;
+
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.serialization.Serializer;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.util.binary.Endian;
+import org.simantics.databoard.util.binary.UTF8;
+
+/**
+ * This is an utility class that encapsulates the databoard value encoding scheme.
+ * It can be used for streaming value writing.
+ */
+public class DataWriter {
+ private static final Serializer DATATYPE_SERIALIZER = Bindings.getSerializerUnchecked(Bindings.getBindingUnchecked( Datatype.class ));
+
+ private final DataOutput out;
+
+ public DataWriter(DataOutput out) {
+ this.out = out;
+ }
+
+ public DataWriter(OutputStream stream) {
+ this.out = new DataOutputStream(stream);
+ }
+
+ public void writeBoolean(boolean value) throws IOException {
+ out.write(value ? 1 : 0);
+ }
+
+ public void writeByte(byte value) throws IOException {
+ out.write(value);
+ }
+
+ public void writeInteger(int value) throws IOException {
+ out.writeInt(value);
+ }
+
+ public void writeLong(long value) throws IOException {
+ out.writeLong(value);
+ }
+
+ public void writeFloat(float value) throws IOException {
+ out.writeFloat(value);
+ }
+
+ public void writeDouble(double value) throws IOException {
+ out.writeDouble(value);
+ }
+
+ public void writeString(String value) throws IOException {
+ int utflen = UTF8.getModifiedUTF8EncodingByteLength(value);
+ Endian.writeDynamicUInt32(out, utflen);
+ UTF8.writeModifiedUTF(out, value);
+ }
+
+ public void writeDatatype(Datatype datatype) throws IOException {
+ DATATYPE_SERIALIZER.serialize(out, datatype);
+ }
+
+ /**
+ * A variable length array is started with the length
+ * followed by the serialization of all elements.
+ */
+ public void beginVariableLengthArray(int length) throws IOException {
+ out.writeInt(length);
+ }
+
+ /**
+ * A map is started with its size followed by
+ * serialization of interleaved keys and values.
+ */
+ public void beginMap(int size) throws IOException {
+ out.writeInt(size);
+ }
+
+ /**
+ * An optional value that is null is written as byte 0.
+ */
+ public void writeOptionalNull() throws IOException {
+ out.write(0);
+ }
+
+ /**
+ * An optional value that is not null is started
+ * with byte 1 followed by the actual value.
+ */
+ public void beginOptionalValue() throws IOException {
+ out.write(1);
+ }
+
+ /**
+ * Selects the constructor of the union type.
+ * It is written as a variable length integer,
+ * so the total number of tags is required.
+ */
+ public void writeUnionTag(int tag, int tagCount) throws IOException {
+ Endian.putUInt(out, tag, tagCount-1);
+ }
+
+ public void writeReferenceToKnownReferableRecord(int id) throws IOException {
+ out.writeInt(id);
+ }
+
+ public void beginUnknownReferableRecord(int id) throws IOException {
+ out.writeInt(0);
+ out.writeInt(id);
+ }
+}