followFars easy case

This commit is contained in:
David Renshaw 2014-06-17 19:41:19 -04:00
parent bf7bcaa56f
commit 9ec8a9b67e
2 changed files with 70 additions and 26 deletions

View file

@ -19,6 +19,13 @@ public final class StructBuilder {
this.bit0Offset = bit0Offset; this.bit0Offset = bit0Offset;
} }
public final StructReader asReader() {
return new StructReader(this.segment,
this.data, this.pointers, this.dataSize,
this.pointerCount, this.bit0Offset,
0x7fffffff);
}
public final boolean getBooleanField(int offset) { public final boolean getBooleanField(int offset) {
int bitOffset = (offset == 0 ? this.bit0Offset : offset); int bitOffset = (offset == 0 ? this.bit0Offset : offset);
int position = this.data + (bitOffset / 8); int position = this.data + (bitOffset / 8);

View file

@ -89,6 +89,8 @@ final class WireHelpers {
return new FollowBuilderFarsResult(WirePointer.target(padOffset, pad), pad, resultSegment); return new FollowBuilderFarsResult(WirePointer.target(padOffset, pad), pad, resultSegment);
} }
//# Landing pad is another far pointer. It is followed by a
//# tag describing the pointed-to object.
throw new Error("unimplemented"); throw new Error("unimplemented");
} else { } else {
@ -96,6 +98,27 @@ final class WireHelpers {
} }
} }
static class FollowFarsResult {
public final int ptr;
public final long ref;
public final SegmentReader segment;
FollowFarsResult(int ptr, long ref, SegmentReader segment) {
this.ptr = ptr; this.ref = ref; this.segment = segment;
}
}
public static FollowFarsResult followFars(long ref, int refTarget, SegmentReader segment) {
//# If the segment is null, this is an unchecked message,
//# so there are no FAR pointers.
if (segment != null && WirePointer.kind(ref) == WirePointer.FAR) {
throw new Error("unimplemented");
} else {
return new FollowFarsResult(refTarget, ref, segment);
}
}
public static StructBuilder initStructPointer(int refOffset, public static StructBuilder initStructPointer(int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
StructSize size) { StructSize size) {
@ -297,21 +320,29 @@ final class WireHelpers {
int refOffset, int refOffset,
int nestingLimit) { int nestingLimit) {
// TODO error handling // TODO error handling. is_null
if (nestingLimit < 0) { if (nestingLimit <= 0) {
throw new DecodeException("Message is too deeply nested or contains cycles."); throw new DecodeException("Message is too deeply nested or contains cycles.");
} }
long ref = WirePointer.get(segment.buffer, refOffset); long ref = WirePointer.get(segment.buffer, refOffset);
int ptrOffset = WirePointer.target(refOffset, ref); int refTarget = WirePointer.target(refOffset, ref);
int dataSizeWords = StructPointer.dataSize(ref); FollowFarsResult resolved = followFars(ref, refTarget, segment);
return new StructReader(segment, int dataSizeWords = StructPointer.dataSize(resolved.ref);
ptrOffset * 8,
(ptrOffset + dataSizeWords), if (WirePointer.kind(resolved.ref) != WirePointer.STRUCT) {
dataSizeWords * 64, throw new DecodeException("Message contains non-struct pointer where struct pointer was expected.");
StructPointer.ptrCount(ref), }
// TODO "bounds_check" (read limiting)
return new StructReader(resolved.segment,
resolved.ptr * Constants.BYTES_PER_WORD,
(resolved.ptr + dataSizeWords),
dataSizeWords * Constants.BITS_PER_WORD,
StructPointer.ptrCount(resolved.ref),
(byte)0, (byte)0,
nestingLimit - 1); nestingLimit - 1);
@ -325,21 +356,24 @@ final class WireHelpers {
long ref = WirePointer.get(segment.buffer, refOffset); long ref = WirePointer.get(segment.buffer, refOffset);
// TODO check for null, follow fars, nestingLimit
if (WirePointer.isNull(ref)) { if (WirePointer.isNull(ref)) {
return new ListReader(); return new ListReader();
} }
if (nestingLimit <= 0) {
throw new Error("nesting limit exceeded");
}
int ptrOffset = WirePointer.target(refOffset, ref); int refTarget = WirePointer.target(refOffset, ref);
long ptr = WirePointer.get(segment.buffer, ptrOffset);
switch (ListPointer.elementSize(ref)) { FollowFarsResult resolved = followFars(ref, refTarget, segment);
switch (ListPointer.elementSize(resolved.ref)) {
case FieldSize.INLINE_COMPOSITE : { case FieldSize.INLINE_COMPOSITE : {
int wordCount = ListPointer.inlineCompositeWordCount(ref); int wordCount = ListPointer.inlineCompositeWordCount(resolved.ref);
long tag = ptr; long tag = WirePointer.get(resolved.segment.buffer, resolved.ptr);
ptrOffset += 1; int ptr = resolved.ptr + 1;
// TODO bounds check // TODO bounds check
@ -351,11 +385,11 @@ final class WireHelpers {
// TODO check whether the size is compatible // TODO check whether the size is compatible
return new ListReader(segment, // TODO follow fars return new ListReader(resolved.segment,
ptrOffset * 8, // ptr * Constants.BYTES_PER_WORD,
size, size,
wordsPerElement * 64, wordsPerElement * Constants.BITS_PER_WORD,
StructPointer.dataSize(tag) * 64, StructPointer.dataSize(tag) * Constants.BITS_PER_WORD,
StructPointer.ptrCount(tag), StructPointer.ptrCount(tag),
nestingLimit - 1); nestingLimit - 1);
} }
@ -376,23 +410,26 @@ final class WireHelpers {
return new Text.Reader(java.nio.ByteBuffer.wrap(new byte[0]), 0, 0); return new Text.Reader(java.nio.ByteBuffer.wrap(new byte[0]), 0, 0);
} }
int ptrOffset = WirePointer.target(refOffset, ref); int refTarget = WirePointer.target(refOffset, ref);
int size = ListPointer.elementCount(ref);
if (WirePointer.kind(ref) != WirePointer.LIST) { FollowFarsResult resolved = followFars(ref, refTarget, segment);
int size = ListPointer.elementCount(resolved.ref);
if (WirePointer.kind(resolved.ref) != WirePointer.LIST) {
throw new DecodeException("Message contains non-list pointer where text was expected."); throw new DecodeException("Message contains non-list pointer where text was expected.");
} }
if (ListPointer.elementSize(ref) != FieldSize.BYTE) { if (ListPointer.elementSize(resolved.ref) != FieldSize.BYTE) {
throw new DecodeException("Message contains list pointer of non-bytes where text was expected."); throw new DecodeException("Message contains list pointer of non-bytes where text was expected.");
} }
// TODO bounds check? // TODO bounds check?
if (size == 0 || segment.buffer.get(8 * ptrOffset + size - 1) != 0) { if (size == 0 || resolved.segment.buffer.get(8 * resolved.ptr + size - 1) != 0) {
throw new DecodeException("Message contains text that is not NUL-terminated."); throw new DecodeException("Message contains text that is not NUL-terminated.");
} }
return new Text.Reader(segment.buffer, ptrOffset, size - 1); return new Text.Reader(resolved.segment.buffer, resolved.ptr, size - 1);
} }
} }