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

175 lines
6.4 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();
throw new Error("unimplemented");
}
// 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;
int ptrOffset = allocate(refOffset, segment, roundBytesUpToWords(byteSize), WirePointer.LIST);
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);
}
}