handle empty struct allocation

This commit is contained in:
David Renshaw 2014-10-14 20:17:07 -04:00
parent 6764cc2449
commit 7bc197456d
4 changed files with 37 additions and 3 deletions

View file

@ -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);

View file

@ -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);
} }

View file

@ -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) {

View file

@ -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);
} }