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 builder = new MessageBuilder();
|
||||||
val root = builder.initRoot(TestAnyPointer.factory);
|
val root = builder.initRoot(TestAnyPointer.factory);
|
||||||
|
|
||||||
|
|
||||||
val oldReader = {
|
val oldReader = {
|
||||||
val oldVersion = root.getAnyPointerField().initAs(TestOldVersion.factory);
|
val oldVersion = root.getAnyPointerField().initAs(TestOldVersion.factory);
|
||||||
oldVersion.setOld1(123);
|
oldVersion.setOld1(123);
|
||||||
|
@ -211,6 +210,17 @@ class EncodingSuite extends FunSuite {
|
||||||
assert(12345 == GLOBAL_INT);
|
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:
|
// to debug, do this:
|
||||||
//Serialize.writeMessage((new java.io.FileOutputStream("/Users/dwrensha/Desktop/test.dat")).getChannel(),
|
//Serialize.writeMessage((new java.io.FileOutputStream("/Users/dwrensha/Desktop/test.dat")).getChannel(),
|
||||||
// message);
|
// message);
|
||||||
|
|
|
@ -25,7 +25,7 @@ public final class AnyPointer {
|
||||||
|
|
||||||
public final static class Reader {
|
public final static class Reader {
|
||||||
final SegmentReader segment;
|
final SegmentReader segment;
|
||||||
final int pointer;
|
final int pointer; // offset in words
|
||||||
final int nestingLimit;
|
final int nestingLimit;
|
||||||
|
|
||||||
public Reader(SegmentReader segment, int pointer, int nestingLimit) {
|
public Reader(SegmentReader segment, int pointer, int nestingLimit) {
|
||||||
|
@ -34,6 +34,10 @@ public final class AnyPointer {
|
||||||
this.nestingLimit = nestingLimit;
|
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) {
|
public final <T> T getAs(FromPointerReader<T> factory) {
|
||||||
return factory.fromPointerReader(this.segment, this.pointer, this.nestingLimit);
|
return factory.fromPointerReader(this.segment, this.pointer, this.nestingLimit);
|
||||||
}
|
}
|
||||||
|
@ -48,6 +52,10 @@ public final class AnyPointer {
|
||||||
this.pointer = pointer;
|
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) {
|
public final <T> T getAs(FromPointerBuilder<T> factory) {
|
||||||
return factory.fromPointerBuilder(this.segment, this.pointer);
|
return factory.fromPointerBuilder(this.segment, this.pointer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,10 @@ final class WireHelpers {
|
||||||
int amount, // in words
|
int amount, // in words
|
||||||
byte kind) {
|
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);
|
int ptr = segment.allocate(amount);
|
||||||
if (ptr == SegmentBuilder.FAILED_ALLOCATION) {
|
if (ptr == SegmentBuilder.FAILED_ALLOCATION) {
|
||||||
|
|
|
@ -50,6 +50,19 @@ final class WirePointer {
|
||||||
(((targetOffset - offset) - 1) << 2) | kind);
|
(((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) {
|
public static void setOffsetAndKind(ByteBuffer buffer, int offset, int offsetAndKind) {
|
||||||
buffer.putInt(offset * 8, offsetAndKind);
|
buffer.putInt(offset * 8, offsetAndKind);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue