handle empty struct allocation
This commit is contained in:
parent
6764cc2449
commit
7bc197456d
4 changed files with 37 additions and 3 deletions
|
@ -122,7 +122,6 @@ class EncodingSuite extends FunSuite {
|
|||
val builder = new MessageBuilder();
|
||||
val root = builder.initRoot(TestAnyPointer.factory);
|
||||
|
||||
|
||||
val oldReader = {
|
||||
val oldVersion = root.getAnyPointerField().initAs(TestOldVersion.factory);
|
||||
oldVersion.setOld1(123);
|
||||
|
@ -211,6 +210,17 @@ class EncodingSuite extends FunSuite {
|
|||
assert(12345 == GLOBAL_INT);
|
||||
}
|
||||
|
||||
test("EmptyStruct") {
|
||||
val builder = new MessageBuilder();
|
||||
val root = builder.initRoot(TestAnyPointer.factory);
|
||||
root.hasAnyPointerField() should equal (false);
|
||||
val any = root.getAnyPointerField();
|
||||
any.isNull() should equal (true);
|
||||
any.initAs(TestEmptyStruct.factory);
|
||||
any.isNull() should equal (false);
|
||||
root.hasAnyPointerField() should equal (true);
|
||||
}
|
||||
|
||||
// to debug, do this:
|
||||
//Serialize.writeMessage((new java.io.FileOutputStream("/Users/dwrensha/Desktop/test.dat")).getChannel(),
|
||||
// message);
|
||||
|
|
|
@ -25,7 +25,7 @@ public final class AnyPointer {
|
|||
|
||||
public final static class Reader {
|
||||
final SegmentReader segment;
|
||||
final int pointer;
|
||||
final int pointer; // offset in words
|
||||
final int nestingLimit;
|
||||
|
||||
public Reader(SegmentReader segment, int pointer, int nestingLimit) {
|
||||
|
@ -34,6 +34,10 @@ public final class AnyPointer {
|
|||
this.nestingLimit = nestingLimit;
|
||||
}
|
||||
|
||||
public final boolean isNull() {
|
||||
return WirePointer.isNull(this.segment.buffer.getLong(this.pointer * Constants.BYTES_PER_WORD));
|
||||
}
|
||||
|
||||
public final <T> T getAs(FromPointerReader<T> factory) {
|
||||
return factory.fromPointerReader(this.segment, this.pointer, this.nestingLimit);
|
||||
}
|
||||
|
@ -48,6 +52,10 @@ public final class AnyPointer {
|
|||
this.pointer = pointer;
|
||||
}
|
||||
|
||||
public final boolean isNull() {
|
||||
return WirePointer.isNull(this.segment.buffer.getLong(this.pointer * Constants.BYTES_PER_WORD));
|
||||
}
|
||||
|
||||
public final <T> T getAs(FromPointerBuilder<T> factory) {
|
||||
return factory.fromPointerBuilder(this.segment, this.pointer);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,10 @@ final class WireHelpers {
|
|||
int amount, // in words
|
||||
byte kind) {
|
||||
|
||||
// TODO check for nullness, amount == 0 case.
|
||||
if (amount == 0 && kind == WirePointer.STRUCT) {
|
||||
WirePointer.setKindAndTargetForEmptyStruct(segment.buffer, refOffset);
|
||||
return new AllocateResult(refOffset, refOffset, segment);
|
||||
}
|
||||
|
||||
int ptr = segment.allocate(amount);
|
||||
if (ptr == SegmentBuilder.FAILED_ALLOCATION) {
|
||||
|
|
|
@ -50,6 +50,19 @@ final class WirePointer {
|
|||
(((targetOffset - offset) - 1) << 2) | kind);
|
||||
}
|
||||
|
||||
public static void setKindAndTargetForEmptyStruct(ByteBuffer buffer, int offset) {
|
||||
//# This pointer points at an empty struct. Assuming the
|
||||
//# WirePointer itself is in-bounds, we can set the target to
|
||||
//# point either at the WirePointer itself or immediately after
|
||||
//# it. The latter would cause the WirePointer to be "null"
|
||||
//# (since for an empty struct the upper 32 bits are going to
|
||||
//# be zero). So we set an offset of -1, as if the struct were
|
||||
//# allocated immediately before this pointer, to distinguish
|
||||
//# it from null.
|
||||
|
||||
buffer.putInt(offset * 8, 0xfffffffc);
|
||||
}
|
||||
|
||||
public static void setOffsetAndKind(ByteBuffer buffer, int offset, int offsetAndKind) {
|
||||
buffer.putInt(offset * 8, offsetAndKind);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue