add support for directly serializing a MessageReader

Previously, you would need to copy the message into a MessageBuilder first.
This commit is contained in:
David Renshaw 2021-05-24 11:49:20 -04:00
parent d310db1e88
commit a078df7e4d
3 changed files with 67 additions and 3 deletions

View file

@ -28,6 +28,10 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
/**
* Serialization using the standard (unpacked) stream encoding:
* https://capnproto.org/encoding.html#serialization-over-a-stream
*/
public final class Serialize {
static ByteBuffer makeByteBuffer(int bytes) {
@ -186,9 +190,8 @@ public final class Serialize {
return bytes / Constants.BYTES_PER_WORD;
}
public static void write(WritableByteChannel outputChannel,
MessageBuilder message) throws IOException {
ByteBuffer[] segments = message.getSegmentsForOutput();
private static void writeSegmentTable(WritableByteChannel outputChannel,
ByteBuffer[] segments) throws IOException {
int tableSize = (segments.length + 2) & (~1);
ByteBuffer table = ByteBuffer.allocate(4 * tableSize);
@ -204,6 +207,34 @@ public final class Serialize {
while (table.hasRemaining()) {
outputChannel.write(table);
}
}
/**
* Serializes a MessageBuilder to a WritableByteChannel.
*/
public static void write(WritableByteChannel outputChannel,
MessageBuilder message) throws IOException {
ByteBuffer[] segments = message.getSegmentsForOutput();
writeSegmentTable(outputChannel, segments);
for (ByteBuffer buffer : segments) {
while(buffer.hasRemaining()) {
outputChannel.write(buffer);
}
}
}
/**
* Serializes a MessageReader to a WritableByteChannel.
*/
public static void write(WritableByteChannel outputChannel,
MessageReader message) throws IOException {
ByteBuffer[] segments = new ByteBuffer[message.arena.segments.size()];
for (int ii = 0 ; ii < message.arena.segments.size(); ++ii) {
segments[ii] = message.arena.segments.get(ii).buffer.duplicate();
}
writeSegmentTable(outputChannel, segments);
for (ByteBuffer buffer : segments) {
while(buffer.hasRemaining()) {

View file

@ -21,6 +21,9 @@
package org.capnproto;
/**
* Serialization using the packed encoding: https://capnproto.org/encoding.html#packing
*/
public final class SerializePacked {
public static MessageReader read(BufferedInputStream input) throws java.io.IOException {
@ -42,16 +45,42 @@ public final class SerializePacked {
return Serialize.read(packedInput, options);
}
/**
* Serializes a MessageBuilder to a BufferedOutputStream.
*/
public static void write(BufferedOutputStream output,
MessageBuilder message) throws java.io.IOException {
PackedOutputStream packedOutputStream = new PackedOutputStream(output);
Serialize.write(packedOutputStream, message);
}
/**
* Serializes a MessageReader to a BufferedOutputStream.
*/
public static void write(BufferedOutputStream output,
MessageReader message) throws java.io.IOException {
PackedOutputStream packedOutputStream = new PackedOutputStream(output);
Serialize.write(packedOutputStream, message);
}
/**
* Serializes a MessageBuilder to an unbuffered output stream.
*/
public static void writeToUnbuffered(java.nio.channels.WritableByteChannel output,
MessageBuilder message) throws java.io.IOException {
BufferedOutputStreamWrapper buffered = new BufferedOutputStreamWrapper(output);
write(buffered, message);
buffered.flush();
}
/**
* Serializes a MessageReader to an unbuffered output stream.
*/
public static void writeToUnbuffered(java.nio.channels.WritableByteChannel output,
MessageReader message) throws java.io.IOException {
BufferedOutputStreamWrapper buffered = new BufferedOutputStreamWrapper(output);
write(buffered, message);
buffered.flush();
}
}

View file

@ -55,6 +55,10 @@ public class SerializeTest {
{
MessageReader messageReader = Serialize.read(new ArrayInputStream(ByteBuffer.wrap(exampleBytes)));
checkSegmentContents(exampleSegmentCount, messageReader.arena);
byte[] outputBytes = new byte[exampleBytes.length];
Serialize.write(new ArrayOutputStream(ByteBuffer.wrap(outputBytes)), messageReader);
Assert.assertArrayEquals(exampleBytes, outputBytes);
}
// ------