followFars easy case
This commit is contained in:
parent
bf7bcaa56f
commit
9ec8a9b67e
2 changed files with 70 additions and 26 deletions
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue