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); } }