capnproto-java-rpc/generator/src/main/java/org/capnproto/WireHelpers.java

192 lines
7.3 KiB
Java
Raw Normal View History

package org.capnproto;
final class WireHelpers {
public static int roundBytesUpToWords(int bytes) {
return (bytes + 7) / 8;
}
public static int allocate(int refOffset,
SegmentBuilder segment,
int amount,
byte kind) {
// TODO check for nullness, amount == 0 case.
int allocation = segment.allocate(amount);
if (allocation == SegmentBuilder.FAILED_ALLOCATION) {
//# Need to allocate in a new segment. We'll need to
//# allocate an extra pointer worth of space to act as
//# the landing pad for a far pointer.
throw new Error("unimplemented");
} else {
WirePointer.setKindAndTarget(segment.buffer, refOffset, kind, allocation);
return allocation;
}
}
public static ListBuilder initListPointer(int refOffset,
SegmentBuilder segment,
int elementCount,
byte elementSize) {
throw new Error("unimplemented");
}
public static ListBuilder initStructListPointer(int refOffset,
SegmentBuilder segment,
int elementCount,
StructSize elementSize) {
if (elementSize.preferredListEncoding != FieldSize.INLINE_COMPOSITE) {
//# Small data-only struct. Allocate a list of primitives instead.
return initListPointer(refOffset, segment, elementCount,
elementSize.preferredListEncoding);
}
int wordsPerElement = elementSize.total();
2014-05-17 20:04:51 +00:00
//# Allocate the list, prefixed by a single WirePointer.
int wordCount = elementCount * wordsPerElement;
int ptrOffset = allocate(refOffset, segment, 1 + wordCount, WirePointer.LIST);
//# Initialize the pointer.
ListPointer.setInlineComposite(segment.buffer, refOffset, wordCount);
WirePointer.setKindAndInlineCompositeListElementCount(segment.buffer, ptrOffset,
WirePointer.STRUCT, elementCount);
2014-05-17 20:57:13 +00:00
StructPointer.setFromStructSize(segment.buffer, ptrOffset, elementSize);
2014-05-17 20:04:51 +00:00
2014-05-17 20:57:13 +00:00
ptrOffset += 1;
return new ListBuilder(segment, ptrOffset, elementCount, wordsPerElement * 64,
elementSize.data * 64, elementSize.pointers);
}
// size is in bytes
public static void initTextPointer(int refOffset,
SegmentBuilder segment,
int size) {
//# The byte list must include a NUL terminator.
int byteSize = size + 1;
2014-05-17 20:57:13 +00:00
//# Allocate the space.
int ptrOffset = allocate(refOffset, segment, roundBytesUpToWords(byteSize), WirePointer.LIST);
2014-05-17 20:57:13 +00:00
//# Initialize the pointer.
ListPointer.set(segment.buffer, refOffset, FieldSize.BYTE, byteSize);
throw new Error("unimplemented");
}
public static void setTextPointer(int refOffset,
SegmentBuilder segment,
Text.Reader value) {
throw new Error("unimplemented");
}
public static StructReader readStructPointer(SegmentReader segment,
int refOffset,
int nestingLimit) {
// TODO error handling
if (nestingLimit < 0) {
throw new DecodeException("Message is too deeply nested or contains cycles.");
}
long ref = WirePointer.get(segment.buffer, refOffset);
int ptrOffset = WirePointer.target(refOffset, ref);
int structPtr = WirePointer.structPointer(ref);
int dataSizeWords = StructPointer.dataSize(structPtr);
return new StructReader(segment,
ptrOffset * 8,
(ptrOffset + dataSizeWords),
dataSizeWords * 64,
StructPointer.ptrCount(structPtr),
(byte)0,
nestingLimit - 1);
}
public static ListReader readListPointer(SegmentReader segment,
int refOffset,
byte expectedElementSize,
int nestingLimit) {
long ref = WirePointer.get(segment.buffer, refOffset);
// TODO check for null, follow fars, nestingLimit
if (WirePointer.isNull(ref)) {
return new ListReader();
}
int listPtr = WirePointer.listPointer(ref);
int ptrOffset = WirePointer.target(refOffset, ref);
long ptr = WirePointer.get(segment.buffer, ptrOffset);
switch (ListPointer.elementSize(listPtr)) {
case FieldSize.INLINE_COMPOSITE : {
int wordCount = ListPointer.inlineCompositeWordCount(listPtr);
long tag = ptr;
ptrOffset += 1;
// TODO bounds check
int size = WirePointer.inlineCompositeListElementCount(tag);
int structPtr = WirePointer.structPointer(tag);
int wordsPerElement = StructPointer.wordSize(structPtr);
// TODO check that elemements do not overrun word count
// TODO check whether the size is compatible
return new ListReader(segment, // TODO follow fars
ptrOffset * 8, //
size,
wordsPerElement * 64,
StructPointer.dataSize(structPtr) * 64,
StructPointer.ptrCount(structPtr),
nestingLimit - 1);
}
case FieldSize.VOID : break;
default :
throw new Error("unrecognized element size");
}
throw new Error();
}
public static Text.Reader readTextPointer(SegmentReader segment,
int refOffset) {
long ref = WirePointer.get(segment.buffer, refOffset);
if (WirePointer.isNull(ref)) {
// XXX should use the default value
return new Text.Reader(java.nio.ByteBuffer.wrap(new byte[0]), 0, 0);
}
int ptrOffset = WirePointer.target(refOffset, ref);
int listPtr = WirePointer.listPointer(ref);
int size = ListPointer.elementCount(listPtr);
if (WirePointer.kind(ref) != WirePointer.LIST) {
throw new DecodeException("Message contains non-list pointer where text was expected.");
}
if (ListPointer.elementSize(listPtr) != FieldSize.BYTE) {
throw new DecodeException("Message contains list pointer of non-bytes where text was expected.");
}
// TODO bounds check?
if (size == 0 || segment.buffer.get(8 * ptrOffset + size - 1) != 0) {
throw new DecodeException("Message contains text that is not NUL-terminated.");
}
return new Text.Reader(segment.buffer, ptrOffset, size - 1);
}
}