CapTables everywhere!

Imbue readers and writers with capTables.
Ensure caps are removed when pointers are zeroed out.
This commit is contained in:
Vaci Koblizek 2020-10-02 21:47:25 +01:00
parent 1913b6d5ea
commit c938938808
21 changed files with 388 additions and 228 deletions

View file

@ -23,35 +23,24 @@ package org.capnproto;
public final class AnyPointer { public final class AnyPointer {
public static final class Factory implements PointerFactory<Builder, Reader> { public static final class Factory implements PointerFactory<Builder, Reader> {
public final Reader fromPointerReader(SegmentReader segment, int pointer, int nestingLimit) {
return new Reader(segment, pointer, nestingLimit);
}
public final Reader fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) { public final Reader fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) {
var result = new Reader(segment, pointer, nestingLimit); return new Reader(segment, capTable, pointer, nestingLimit);
result.capTable = capTable;
return result;
}
public final Builder fromPointerBuilder(SegmentBuilder segment, int pointer) {
return new Builder(segment, pointer);
} }
public final Builder fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) { public final Builder fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) {
var result = new Builder(segment, pointer); return new Builder(segment, capTable, pointer);
result.capTable = capTable;
return result;
} }
public final Builder initFromPointerBuilder(SegmentBuilder segment, int pointer, int elementCount) { public final Builder initFromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, int elementCount) {
Builder result = new Builder(segment, pointer); Builder result = new Builder(segment, capTable, pointer);
result.clear(); result.clear();
return result; return result;
} }
} }
public static final Factory factory = new Factory(); public static final Factory factory = new Factory();
public final static class Reader { public final static class Reader extends Capability.ReaderContext {
final SegmentReader segment; final SegmentReader segment;
final int pointer; // offset in words final int pointer; // offset in words
final int nestingLimit; final int nestingLimit;
CapTableReader capTable;
public Reader(SegmentReader segment, int pointer, int nestingLimit) { public Reader(SegmentReader segment, int pointer, int nestingLimit) {
this.segment = segment; this.segment = segment;
@ -59,6 +48,13 @@ public final class AnyPointer {
this.nestingLimit = nestingLimit; this.nestingLimit = nestingLimit;
} }
public Reader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) {
this.segment = segment;
this.pointer = pointer;
this.nestingLimit = nestingLimit;
this.capTable = capTable;
}
final Reader imbue(CapTableReader capTable) { final Reader imbue(CapTableReader capTable) {
var result = new Reader(segment, pointer, nestingLimit); var result = new Reader(segment, pointer, nestingLimit);
result.capTable = capTable; result.capTable = capTable;
@ -94,20 +90,23 @@ public final class AnyPointer {
} }
} }
public static final class Builder { public static final class Builder extends Capability.BuilderContext {
final SegmentBuilder segment; final SegmentBuilder segment;
final int pointer; final int pointer;
CapTableBuilder capTable;
public Builder(SegmentBuilder segment, int pointer) { public Builder(SegmentBuilder segment, int pointer) {
this.segment = segment; this.segment = segment;
this.pointer = pointer; this.pointer = pointer;
} }
Builder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) {
this.segment = segment;
this.pointer = pointer;
this.capTable = capTable;
}
final Builder imbue(CapTableBuilder capTable) { final Builder imbue(CapTableBuilder capTable) {
var result = new Builder(segment, pointer); return new Builder(segment, capTable, pointer);
result.capTable = capTable;
return result;
} }
public final boolean isNull() { public final boolean isNull() {
@ -115,19 +114,19 @@ public final class AnyPointer {
} }
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.capTable, this.pointer);
} }
public final <T> T initAs(FromPointerBuilder<T> factory) { public final <T> T initAs(FromPointerBuilder<T> factory) {
return factory.initFromPointerBuilder(this.segment, this.pointer, 0); return factory.initFromPointerBuilder(this.segment, this.capTable, this.pointer, 0);
} }
public final <T> T initAs(FromPointerBuilder<T> factory, int elementCount) { public final <T> T initAs(FromPointerBuilder<T> factory, int elementCount) {
return factory.initFromPointerBuilder(this.segment, this.pointer, elementCount); return factory.initFromPointerBuilder(this.segment, this.capTable, this.pointer, elementCount);
} }
public final <T, U> void setAs(SetPointerBuilder<T, U> factory, U reader) { public final <T, U> void setAs(SetPointerBuilder<T, U> factory, U reader) {
factory.setPointerBuilder(this.segment, this.pointer, reader); factory.setPointerBuilder(this.segment, this.capTable, this.pointer, reader);
} }
public final void setAsCapability(Capability.Client cap) { public final void setAsCapability(Capability.Client cap) {
@ -135,11 +134,11 @@ public final class AnyPointer {
} }
public final Reader asReader() { public final Reader asReader() {
return new Reader(segment, pointer, java.lang.Integer.MAX_VALUE); return new Reader(segment, this.capTable, pointer, java.lang.Integer.MAX_VALUE);
} }
public final void clear() { public final void clear() {
WireHelpers.zeroObject(this.segment, this.pointer); WireHelpers.zeroObject(this.segment, this.capTable, this.pointer);
this.segment.buffer.putLong(this.pointer * 8, 0L); this.segment.buffer.putLong(this.pointer * 8, 0L);
} }
} }

View file

@ -40,44 +40,41 @@ public final class Data {
} }
@Override @Override
public Reader fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) { public final Reader fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) {
return fromPointerReader(segment, pointer, nestingLimit); return WireHelpers.readDataPointer(segment, pointer, null, 0, 0);
} }
@Override @Override
public final Builder fromPointerBuilderBlobDefault( public final Builder fromPointerBuilderBlobDefault(
SegmentBuilder segment, SegmentBuilder segment,
CapTableBuilder capTable,
int pointer, int pointer,
java.nio.ByteBuffer defaultBuffer, java.nio.ByteBuffer defaultBuffer,
int defaultOffset, int defaultOffset,
int defaultSize) { int defaultSize) {
return WireHelpers.getWritableDataPointer(pointer, return WireHelpers.getWritableDataPointer(pointer,
segment, segment,
capTable,
defaultBuffer, defaultBuffer,
defaultOffset, defaultOffset,
defaultSize); defaultSize);
} }
@Override @Override
public final Builder fromPointerBuilder(SegmentBuilder segment, int pointer) { public final Builder fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) {
return WireHelpers.getWritableDataPointer(pointer, return WireHelpers.getWritableDataPointer(pointer,
segment, segment,
capTable,
null, 0, 0); null, 0, 0);
} }
@Override @Override
public Builder fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) { public final Builder initFromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, int size) {
return fromPointerBuilder(segment, pointer); return WireHelpers.initDataPointer(pointer, segment, capTable, size);
} }
@Override @Override
public final Builder initFromPointerBuilder(SegmentBuilder segment, int pointer, int size) { public final void setPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, Reader value) {
return WireHelpers.initDataPointer(pointer, segment, size); WireHelpers.setDataPointer(pointer, segment, capTable, value);
}
@Override
public final void setPointerBuilder(SegmentBuilder segment, int pointer, Reader value) {
WireHelpers.setDataPointer(pointer, segment, value);
} }
} }
public static final Factory factory = new Factory(); public static final Factory factory = new Factory();

View file

@ -22,13 +22,14 @@
package org.capnproto; package org.capnproto;
public interface FromPointerBuilder<T> { public interface FromPointerBuilder<T> {
T fromPointerBuilder(SegmentBuilder segment, int pointer); default T fromPointerBuilder(SegmentBuilder segment, int pointer) {
default T fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) {
return fromPointerBuilder(segment, pointer); return fromPointerBuilder(segment, pointer);
} }
T initFromPointerBuilder(SegmentBuilder segment, int pointer, int elementCount);
default T initFromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, int elementCount) { T fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer);
return initFromPointerBuilder(segment, pointer, elementCount);
default T initFromPointerBuilder(SegmentBuilder segment, int pointer, int elementCount) {
return initFromPointerBuilder(segment, null, pointer, elementCount);
} }
T initFromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, int elementCount);
} }

View file

@ -22,6 +22,11 @@
package org.capnproto; package org.capnproto;
public interface FromPointerBuilderBlobDefault<T> { public interface FromPointerBuilderBlobDefault<T> {
T fromPointerBuilderBlobDefault(SegmentBuilder segment, int pointer, default T fromPointerBuilderBlobDefault(SegmentBuilder segment, int pointer,
java.nio.ByteBuffer defaultBuffer, int defaultOffset, int defaultSize) {
return fromPointerBuilderBlobDefault(segment, null, pointer, defaultBuffer, defaultOffset, defaultSize);
}
T fromPointerBuilderBlobDefault(SegmentBuilder segment, CapTableBuilder capTable, int pointer,
java.nio.ByteBuffer defaultBuffer, int defaultOffset, int defaultSize); java.nio.ByteBuffer defaultBuffer, int defaultOffset, int defaultSize);
} }

View file

@ -22,5 +22,10 @@
package org.capnproto; package org.capnproto;
public interface FromPointerBuilderRefDefault<T> { public interface FromPointerBuilderRefDefault<T> {
T fromPointerBuilderRefDefault(SegmentBuilder segment, int pointer, SegmentReader defaultSegment, int defaultOffset);
default T fromPointerBuilderRefDefault(SegmentBuilder segment, int pointer, SegmentReader defaultSegment, int defaultOffset) {
return fromPointerBuilderRefDefault(segment, null, pointer, defaultSegment, defaultOffset);
}
T fromPointerBuilderRefDefault(SegmentBuilder segment, CapTableBuilder capTable, int pointer, SegmentReader defaultSegment, int defaultOffset);
} }

View file

@ -22,9 +22,8 @@
package org.capnproto; package org.capnproto;
public interface FromPointerReader<T> { public interface FromPointerReader<T> {
T fromPointerReader(SegmentReader segment, int pointer, int nestingLimit); default T fromPointerReader(SegmentReader segment, int pointer, int nestingLimit) {
return fromPointerReader(segment, null, pointer, nestingLimit);
default T fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) {
return fromPointerReader(segment, pointer, nestingLimit);
} }
T fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit);
} }

View file

@ -22,5 +22,8 @@
package org.capnproto; package org.capnproto;
public interface FromPointerReaderRefDefault<T> { public interface FromPointerReaderRefDefault<T> {
T fromPointerReaderRefDefault(SegmentReader segment, int pointer, SegmentReader defaultSegment, int defaultOffset, int nestingLimit); default T fromPointerReaderRefDefault(SegmentReader segment, int pointer, SegmentReader defaultSegment, int defaultOffset, int nestingLimit) {
return fromPointerReaderRefDefault(segment, null, pointer, defaultSegment, defaultOffset, nestingLimit);
}
T fromPointerReaderRefDefault(SegmentReader segment, CapTableReader capTable, int pointer, SegmentReader defaultSegment, int defaultOffset, int nestingLimit);
} }

View file

@ -21,11 +21,22 @@
package org.capnproto; package org.capnproto;
public class ListBuilder { import java.util.List;
public class ListBuilder extends Capability.BuilderContext {
public interface Factory<T> { public interface Factory<T> {
T constructBuilder(SegmentBuilder segment, int ptr, T constructBuilder(SegmentBuilder segment, int ptr,
int elementCount, int step, int elementCount, int step,
int structDataSize, short structPointerCount); int structDataSize, short structPointerCount);
default T constructBuilder(SegmentBuilder segment, CapTableBuilder capTable, int ptr,
int elementCount, int step,
int structDataSize, short structPointerCount) {
var result = constructBuilder(segment, ptr, elementCount, step, structDataSize, structPointerCount);
if (result instanceof Capability.BuilderContext) {
((Capability.BuilderContext) result).capTable = capTable;
}
return result;
}
} }
final SegmentBuilder segment; final SegmentBuilder segment;
@ -34,7 +45,6 @@ public class ListBuilder {
final int step; // in bits final int step; // in bits
final int structDataSize; // in bits final int structDataSize; // in bits
final short structPointerCount; final short structPointerCount;
CapTableBuilder capTable;
public ListBuilder(SegmentBuilder segment, int ptr, public ListBuilder(SegmentBuilder segment, int ptr,
int elementCount, int step, int elementCount, int step,
@ -120,6 +130,7 @@ public class ListBuilder {
int structPointers = (structData + (this.structDataSize / 8)) / 8; int structPointers = (structData + (this.structDataSize / 8)) / 8;
return factory.constructBuilder(this.segment, return factory.constructBuilder(this.segment,
this.capTable,
structData, structData,
structPointers, structPointers,
this.structDataSize, this.structDataSize,
@ -129,18 +140,21 @@ public class ListBuilder {
protected final <T> T _getPointerElement(FromPointerBuilder<T> factory, int index) { protected final <T> T _getPointerElement(FromPointerBuilder<T> factory, int index) {
return factory.fromPointerBuilder( return factory.fromPointerBuilder(
this.segment, this.segment,
this.capTable,
(this.ptr + (int)((long)index * this.step / Constants.BITS_PER_BYTE)) / Constants.BYTES_PER_WORD); (this.ptr + (int)((long)index * this.step / Constants.BITS_PER_BYTE)) / Constants.BYTES_PER_WORD);
} }
protected final <T> T _initPointerElement(FromPointerBuilder<T> factory, int index, int elementCount) { protected final <T> T _initPointerElement(FromPointerBuilder<T> factory, int index, int elementCount) {
return factory.initFromPointerBuilder( return factory.initFromPointerBuilder(
this.segment, this.segment,
this.capTable,
(this.ptr + (int)((long)index * this.step / Constants.BITS_PER_BYTE)) / Constants.BYTES_PER_WORD, (this.ptr + (int)((long)index * this.step / Constants.BITS_PER_BYTE)) / Constants.BYTES_PER_WORD,
elementCount); elementCount);
} }
protected final <Builder, Reader> void _setPointerElement(SetPointerBuilder<Builder, Reader> factory, int index, Reader value) { protected final <Builder, Reader> void _setPointerElement(SetPointerBuilder<Builder, Reader> factory, int index, Reader value) {
factory.setPointerBuilder(this.segment, factory.setPointerBuilder(this.segment,
this.capTable,
(this.ptr + (int)((long)index * this.step / Constants.BITS_PER_BYTE)) / Constants.BYTES_PER_WORD, (this.ptr + (int)((long)index * this.step / Constants.BITS_PER_BYTE)) / Constants.BYTES_PER_WORD,
value); value);
} }

View file

@ -32,12 +32,13 @@ public abstract class ListFactory<Builder extends ListBuilder, Reader extends Li
final byte elementSize; final byte elementSize;
ListFactory(byte elementSize) {this.elementSize = elementSize;} ListFactory(byte elementSize) {this.elementSize = elementSize;}
public final Reader fromPointerReaderRefDefault(SegmentReader segment, int pointer, public final Reader fromPointerReaderRefDefault(SegmentReader segment, CapTableReader capTable, int pointer,
SegmentReader defaultSegment, int defaultOffset, SegmentReader defaultSegment, int defaultOffset,
int nestingLimit) { int nestingLimit) {
return WireHelpers.readListPointer(this, return WireHelpers.readListPointer(this,
segment, segment,
pointer, pointer,
capTable,
defaultSegment, defaultSegment,
defaultOffset, defaultOffset,
this.elementSize, this.elementSize,
@ -45,44 +46,34 @@ public abstract class ListFactory<Builder extends ListBuilder, Reader extends Li
} }
public final Reader fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) { public final Reader fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) {
var result = fromPointerReader(segment, pointer, nestingLimit); return fromPointerReaderRefDefault(segment, capTable, pointer, null, 0, nestingLimit);
result.capTable = capTable;
return result;
} }
public final Reader fromPointerReader(SegmentReader segment, int pointer, int nestingLimit) { public Builder fromPointerBuilderRefDefault(SegmentBuilder segment, CapTableBuilder capTable, int pointer,
return fromPointerReaderRefDefault(segment, pointer, null, 0, nestingLimit);
}
public Builder fromPointerBuilderRefDefault(SegmentBuilder segment, int pointer,
SegmentReader defaultSegment, int defaultOffset) { SegmentReader defaultSegment, int defaultOffset) {
return WireHelpers.getWritableListPointer(this, return WireHelpers.getWritableListPointer(this,
pointer, pointer,
segment, segment,
capTable,
this.elementSize, this.elementSize,
defaultSegment, defaultSegment,
defaultOffset); defaultOffset);
} }
public Builder fromPointerBuilder(SegmentBuilder segment, int pointer) { public Builder fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) {
return WireHelpers.getWritableListPointer(this, return WireHelpers.getWritableListPointer(this,
pointer, pointer,
segment, segment,
capTable,
this.elementSize, this.elementSize,
null, 0); null, 0);
} }
public final Builder fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) { public Builder initFromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, int elementCount) {
var result = fromPointerBuilder(segment, pointer); return WireHelpers.initListPointer(this, capTable, pointer, segment, elementCount, this.elementSize);
result.capTable = capTable;
return result;
} }
public Builder initFromPointerBuilder(SegmentBuilder segment, int pointer, int elementCount) { public final void setPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, Reader value) {
return WireHelpers.initListPointer(this, pointer, segment, elementCount, this.elementSize); WireHelpers.setListPointer(segment, capTable, pointer, value);
}
public final void setPointerBuilder(SegmentBuilder segment, int pointer, Reader value) {
WireHelpers.setListPointer(segment, pointer, value);
} }
} }

View file

@ -21,13 +21,22 @@
package org.capnproto; package org.capnproto;
public class ListReader { public class ListReader extends Capability.ReaderContext {
public interface Factory<T> { public interface Factory<T> {
T constructReader(SegmentReader segment, T constructReader(SegmentReader segment,
int ptr, int ptr,
int elementCount, int step, int elementCount, int step,
int structDataSize, short structPointerCount, int structDataSize, short structPointerCount,
int nestingLimit); int nestingLimit);
default T constructReader(SegmentBuilder segment, CapTableReader capTable, int ptr,
int elementCount, int step,
int structDataSize, short structPointerCount, int nestingLimit) {
var result = constructReader(segment, ptr, elementCount, step, structDataSize, structPointerCount, nestingLimit);
if (result instanceof Capability.ReaderContext) {
((Capability.ReaderContext) result).capTable = capTable;
}
return result;
}
} }
final SegmentReader segment; final SegmentReader segment;
@ -37,7 +46,6 @@ public class ListReader {
final int structDataSize; // in bits final int structDataSize; // in bits
final short structPointerCount; final short structPointerCount;
final int nestingLimit; final int nestingLimit;
CapTableReader capTable;
public ListReader() { public ListReader() {
this.segment = null; this.segment = null;
@ -60,7 +68,6 @@ public class ListReader {
this.structDataSize = structDataSize; this.structDataSize = structDataSize;
this.structPointerCount = structPointerCount; this.structPointerCount = structPointerCount;
this.nestingLimit = nestingLimit; this.nestingLimit = nestingLimit;
} }
ListReader imbue(CapTableReader capTable) { ListReader imbue(CapTableReader capTable) {

View file

@ -22,5 +22,5 @@
package org.capnproto; package org.capnproto;
public interface SetPointerBuilder<Builder, Reader> { public interface SetPointerBuilder<Builder, Reader> {
void setPointerBuilder(SegmentBuilder segment, int pointer, Reader value); void setPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, Reader value);
} }

View file

@ -21,10 +21,18 @@
package org.capnproto; package org.capnproto;
public class StructBuilder { public class StructBuilder extends Capability.BuilderContext {
public interface Factory<T> { public interface Factory<T> {
T constructBuilder(SegmentBuilder segment, int data, int pointers, int dataSize, T constructBuilder(SegmentBuilder segment, int data, int pointers, int dataSize,
short pointerCount); short pointerCount);
default T constructBuilder(SegmentBuilder segment, CapTableBuilder capTable, int data, int pointers, int dataSize,
short pointerCount) {
var result = constructBuilder(segment, data, pointers, dataSize, pointerCount);
if (result instanceof Capability.BuilderContext) {
((Capability.BuilderContext) result).capTable = capTable;
}
return result;
}
StructSize structSize(); StructSize structSize();
} }
@ -33,7 +41,6 @@ public class StructBuilder {
protected final int pointers; // word offset of pointer section protected final int pointers; // word offset of pointer section
protected final int dataSize; // in bits protected final int dataSize; // in bits
protected final short pointerCount; protected final short pointerCount;
protected CapTableBuilder capTable;
public StructBuilder(SegmentBuilder segment, int data, public StructBuilder(SegmentBuilder segment, int data,
int pointers, int dataSize, short pointerCount) { int pointers, int dataSize, short pointerCount) {
@ -44,12 +51,6 @@ public class StructBuilder {
this.pointerCount = pointerCount; this.pointerCount = pointerCount;
} }
StructBuilder imbue(CapTableBuilder capTable) {
var result = new StructBuilder(this.segment, this.data, this.pointers, this.dataSize, this.pointerCount);
result.capTable = capTable;
return result;
}
protected final boolean _getBooleanField(int offset) { protected final boolean _getBooleanField(int offset) {
int bitOffset = offset; int bitOffset = offset;
int position = this.data + (bitOffset / 8); int position = this.data + (bitOffset / 8);
@ -179,30 +180,30 @@ public class StructBuilder {
protected final void _clearPointerField(int ptrIndex) { protected final void _clearPointerField(int ptrIndex) {
int pointer = this.pointers + ptrIndex; int pointer = this.pointers + ptrIndex;
WireHelpers.zeroObject(this.segment, pointer); WireHelpers.zeroObject(this.segment, this.capTable, pointer);
this.segment.buffer.putLong(pointer * 8, 0L); this.segment.buffer.putLong(pointer * 8, 0L);
} }
protected final <T> T _getPointerField(FromPointerBuilder<T> factory, int index) { protected final <T> T _getPointerField(FromPointerBuilder<T> factory, int index) {
return factory.fromPointerBuilder(this.segment, this.pointers + index); return factory.fromPointerBuilder(this.segment, this.capTable, this.pointers + index);
} }
protected final <T> T _getPointerField(FromPointerBuilderRefDefault<T> factory, int index, protected final <T> T _getPointerField(FromPointerBuilderRefDefault<T> factory, int index,
SegmentReader defaultSegment, int defaultOffset) { SegmentReader defaultSegment, int defaultOffset) {
return factory.fromPointerBuilderRefDefault(this.segment, this.pointers + index, defaultSegment, defaultOffset); return factory.fromPointerBuilderRefDefault(this.segment, this.capTable, this.pointers + index, defaultSegment, defaultOffset);
} }
protected final <T> T _getPointerField(FromPointerBuilderBlobDefault<T> factory, int index, protected final <T> T _getPointerField(FromPointerBuilderBlobDefault<T> factory, int index,
java.nio.ByteBuffer defaultBuffer, int defaultOffset, int defaultSize) { java.nio.ByteBuffer defaultBuffer, int defaultOffset, int defaultSize) {
return factory.fromPointerBuilderBlobDefault(this.segment, this.pointers + index, defaultBuffer, defaultOffset, defaultSize); return factory.fromPointerBuilderBlobDefault(this.segment, this.capTable, this.pointers + index, defaultBuffer, defaultOffset, defaultSize);
} }
protected final <T> T _initPointerField(FromPointerBuilder<T> factory, int index, int elementCount) { protected final <T> T _initPointerField(FromPointerBuilder<T> factory, int index, int elementCount) {
return factory.initFromPointerBuilder(this.segment, this.pointers + index, elementCount); return factory.initFromPointerBuilder(this.segment, this.capTable, this.pointers + index, elementCount);
} }
protected final <Builder, Reader> void _setPointerField(SetPointerBuilder<Builder, Reader> factory, int index, Reader value) { protected final <Builder, Reader> void _setPointerField(SetPointerBuilder<Builder, Reader> factory, int index, Reader value) {
factory.setPointerBuilder(this.segment, this.pointers + index, value); factory.setPointerBuilder(this.segment, this.capTable, this.pointers + index, value);
} }
protected final void _copyContentFrom(StructReader other) { protected final void _copyContentFrom(StructReader other) {
@ -251,14 +252,16 @@ public class StructBuilder {
// Zero out all pointers in the target. // Zero out all pointers in the target.
for (int ii = 0; ii < this.pointerCount; ++ii) { for (int ii = 0; ii < this.pointerCount; ++ii) {
WireHelpers.zeroObject(this.segment, this.pointers + ii); WireHelpers.zeroObject(this.segment, this.capTable, this.pointers + ii);
} }
this.segment.buffer.putLong(this.pointers * Constants.BYTES_PER_WORD, 0); this.segment.buffer.putLong(this.pointers * Constants.BYTES_PER_WORD, 0);
for (int ii = 0; ii < sharedPointerCount; ++ii) { for (int ii = 0; ii < sharedPointerCount; ++ii) {
WireHelpers.copyPointer(this.segment, WireHelpers.copyPointer(this.segment,
this.capTable,
this.pointers + ii, this.pointers + ii,
other.segment, other.segment,
other.capTable,
other.pointers + ii, other.pointers + ii,
other.nestingLimit); other.nestingLimit);
} }

View file

@ -28,44 +28,35 @@ public abstract class StructFactory<Builder extends StructBuilder, Reader extend
SetPointerBuilder<Builder, Reader>, SetPointerBuilder<Builder, Reader>,
FromPointerReaderRefDefault<Reader>, FromPointerReaderRefDefault<Reader>,
StructReader.Factory<Reader> { StructReader.Factory<Reader> {
public final Reader fromPointerReaderRefDefault(SegmentReader segment, int pointer, public final Reader fromPointerReaderRefDefault(SegmentReader segment, CapTableReader capTable, int pointer,
SegmentReader defaultSegment, int defaultOffset, SegmentReader defaultSegment, int defaultOffset,
int nestingLimit) { int nestingLimit) {
return WireHelpers.readStructPointer(this, return WireHelpers.readStructPointer(this,
segment, segment,
capTable,
pointer, pointer,
defaultSegment, defaultOffset, defaultSegment, defaultOffset,
nestingLimit); nestingLimit);
} }
public final Reader fromPointerReader(SegmentReader segment, int pointer, int nestingLimit) {
return fromPointerReaderRefDefault(segment, pointer, null, 0, nestingLimit);
}
public final Reader fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) { public final Reader fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) {
var result = fromPointerReaderRefDefault(segment, pointer, null, 0, nestingLimit); return fromPointerReaderRefDefault(segment, capTable, pointer, null, 0, nestingLimit);
result.capTable = capTable;
return result;
} }
public final Builder fromPointerBuilderRefDefault(SegmentBuilder segment, int pointer, public final Builder fromPointerBuilderRefDefault(SegmentBuilder segment, CapTableBuilder capTable, int pointer,
SegmentReader defaultSegment, int defaultOffset) { SegmentReader defaultSegment, int defaultOffset) {
return WireHelpers.getWritableStructPointer(this, pointer, segment, this.structSize(), return WireHelpers.getWritableStructPointer(this, pointer, segment, capTable, this.structSize(),
defaultSegment, defaultOffset); defaultSegment, defaultOffset);
} }
public final Builder fromPointerBuilder(SegmentBuilder segment, int pointer) {
return WireHelpers.getWritableStructPointer(this, pointer, segment, this.structSize(),
null, 0);
}
public final Builder fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) { public final Builder fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) {
var result = fromPointerBuilder(segment, pointer); return WireHelpers.getWritableStructPointer(this, pointer, segment, capTable, this.structSize(),
result.capTable = capTable; null, 0);
return result;
} }
public final Builder initFromPointerBuilder(SegmentBuilder segment, int pointer, int elementCount) { public final Builder initFromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, int elementCount) {
return WireHelpers.initStructPointer(this, pointer, segment, this.structSize()); return WireHelpers.initStructPointer(this, pointer, segment, capTable, this.structSize());
} }
public final void setPointerBuilder(SegmentBuilder segment, int pointer, Reader value) { public final void setPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, Reader value) {
WireHelpers.setStructPointer(segment, pointer, value); WireHelpers.setStructPointer(segment, capTable, pointer, value);
} }
public abstract Reader asReader(Builder builder); public abstract Reader asReader(Builder builder);

View file

@ -56,9 +56,10 @@ public final class StructList {
} }
@Override @Override
public final Builder<ElementBuilder> fromPointerBuilderRefDefault(SegmentBuilder segment, int pointer, public final Builder<ElementBuilder> fromPointerBuilderRefDefault(SegmentBuilder segment, CapTableBuilder capTable, int pointer,
SegmentReader defaultSegment, int defaultOffset) { SegmentReader defaultSegment, int defaultOffset) {
return WireHelpers.getWritableStructListPointer(this, return WireHelpers.getWritableStructListPointer(this,
capTable,
pointer, pointer,
segment, segment,
factory.structSize(), factory.structSize(),
@ -67,8 +68,9 @@ public final class StructList {
} }
@Override @Override
public final Builder<ElementBuilder> fromPointerBuilder(SegmentBuilder segment, int pointer) { public final Builder<ElementBuilder> fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) {
return WireHelpers.getWritableStructListPointer(this, return WireHelpers.getWritableStructListPointer(this,
capTable,
pointer, pointer,
segment, segment,
factory.structSize(), factory.structSize(),
@ -76,9 +78,9 @@ public final class StructList {
} }
@Override @Override
public final Builder<ElementBuilder> initFromPointerBuilder(SegmentBuilder segment, int pointer, public final Builder<ElementBuilder> initFromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer,
int elementCount) { int elementCount) {
return WireHelpers.initStructListPointer(this, pointer, segment, elementCount, factory.structSize()); return WireHelpers.initStructListPointer(this, capTable, pointer, segment, elementCount, factory.structSize());
} }
} }

View file

@ -21,11 +21,20 @@
package org.capnproto; package org.capnproto;
public class StructReader { public class StructReader extends Capability.ReaderContext {
public interface Factory<T> { public interface Factory<T> {
abstract T constructReader(SegmentReader segment, int data, int pointers, T constructReader(SegmentReader segment, int data, int pointers,
int dataSize, short pointerCount, int dataSize, short pointerCount,
int nestingLimit); int nestingLimit);
default T constructReader(SegmentReader segment, CapTableReader capTable, int data, int pointers,
int dataSize, short pointerCount,
int nestingLimit) {
var result = constructReader(segment, data, pointers, dataSize, pointerCount, nestingLimit);
if (result instanceof Capability.ReaderContext) {
((Capability.ReaderContext) result).capTable = capTable;
}
return result;
}
} }
protected final SegmentReader segment; protected final SegmentReader segment;
@ -34,7 +43,6 @@ public class StructReader {
protected final int dataSize; // in bits protected final int dataSize; // in bits
protected final short pointerCount; protected final short pointerCount;
protected final int nestingLimit; protected final int nestingLimit;
protected CapTableReader capTable;
public StructReader() { public StructReader() {
this.segment = SegmentReader.EMPTY; this.segment = SegmentReader.EMPTY;
@ -169,6 +177,7 @@ public class StructReader {
this.nestingLimit); this.nestingLimit);
} else { } else {
return factory.fromPointerReader(SegmentReader.EMPTY, return factory.fromPointerReader(SegmentReader.EMPTY,
this.capTable,
0, 0,
this.nestingLimit); this.nestingLimit);
} }
@ -179,12 +188,14 @@ public class StructReader {
SegmentReader defaultSegment, int defaultOffset) { SegmentReader defaultSegment, int defaultOffset) {
if (ptrIndex < this.pointerCount) { if (ptrIndex < this.pointerCount) {
return factory.fromPointerReaderRefDefault(this.segment, return factory.fromPointerReaderRefDefault(this.segment,
this.capTable,
this.pointers + ptrIndex, this.pointers + ptrIndex,
defaultSegment, defaultSegment,
defaultOffset, defaultOffset,
this.nestingLimit); this.nestingLimit);
} else { } else {
return factory.fromPointerReaderRefDefault(SegmentReader.EMPTY, return factory.fromPointerReaderRefDefault(SegmentReader.EMPTY,
this.capTable,
0, 0,
defaultSegment, defaultSegment,
defaultOffset, defaultOffset,

View file

@ -37,45 +37,37 @@ public final class Text {
} }
@Override @Override
public final Reader fromPointerReader(SegmentReader segment, int pointer, int nestingLimit) { public final Reader fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) {
return WireHelpers.readTextPointer(segment, pointer, null, 0, 0); return WireHelpers.readTextPointer(segment, pointer, null, 0, 0);
} }
@Override @Override
public final Reader fromPointerReader(SegmentReader segment, CapTableReader capTable, int pointer, int nestingLimit) { public final Builder fromPointerBuilderBlobDefault(SegmentBuilder segment, CapTableBuilder capTable, int pointer,
return fromPointerReader(segment, pointer, nestingLimit); java.nio.ByteBuffer defaultBuffer, int defaultOffset, int defaultSize) {
}
@Override
public final Builder fromPointerBuilderBlobDefault(SegmentBuilder segment, int pointer,
java.nio.ByteBuffer defaultBuffer, int defaultOffset, int defaultSize) {
return WireHelpers.getWritableTextPointer(pointer, return WireHelpers.getWritableTextPointer(pointer,
segment, segment,
capTable,
defaultBuffer, defaultBuffer,
defaultOffset, defaultOffset,
defaultSize); defaultSize);
} }
@Override @Override
public final Builder fromPointerBuilder(SegmentBuilder segment, int pointer) { public final Builder fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) {
return WireHelpers.getWritableTextPointer(pointer, return WireHelpers.getWritableTextPointer(pointer,
segment, segment,
capTable,
null, 0, 0); null, 0, 0);
} }
@Override @Override
public Builder fromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer) { public Builder initFromPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, int size) {
return fromPointerBuilder(segment, pointer); return WireHelpers.initTextPointer(pointer, segment, capTable, size);
} }
@Override @Override
public final Builder initFromPointerBuilder(SegmentBuilder segment, int pointer, int size) { public void setPointerBuilder(SegmentBuilder segment, CapTableBuilder capTable, int pointer, Reader value) {
return WireHelpers.initTextPointer(pointer, segment, size); WireHelpers.setTextPointer(pointer, segment, capTable, value);
}
@Override
public final void setPointerBuilder(SegmentBuilder segment, int pointer, Reader value) {
WireHelpers.setTextPointer(pointer, segment, value);
} }
} }
public static final Factory factory = new Factory(); public static final Factory factory = new Factory();

View file

@ -49,12 +49,13 @@ final class WireHelpers {
static AllocateResult allocate(int refOffset, static AllocateResult allocate(int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
CapTableBuilder capTable,
int amount, // in words int amount, // in words
byte kind) { byte kind) {
long ref = segment.get(refOffset); long ref = segment.get(refOffset);
if (!WirePointer.isNull(ref)) { if (!WirePointer.isNull(ref)) {
zeroObject(segment, refOffset); zeroObject(segment, capTable, refOffset);
} }
if (amount == 0 && kind == WirePointer.STRUCT) { if (amount == 0 && kind == WirePointer.STRUCT) {
@ -174,7 +175,7 @@ final class WireHelpers {
} }
} }
static void zeroObject(SegmentBuilder segment, int refOffset) { static void zeroObject(SegmentBuilder segment, CapTableBuilder capTable, int refOffset) {
//# Zero out the pointed-to object. Use when the pointer is //# Zero out the pointed-to object. Use when the pointer is
//# about to be overwritten making the target object no longer //# about to be overwritten making the target object no longer
//# reachable. //# reachable.
@ -187,7 +188,7 @@ final class WireHelpers {
switch (WirePointer.kind(ref)) { switch (WirePointer.kind(ref)) {
case WirePointer.STRUCT: case WirePointer.STRUCT:
case WirePointer.LIST: case WirePointer.LIST:
zeroObject(segment, ref, WirePointer.target(refOffset, ref)); zeroObject(segment, capTable, ref, WirePointer.target(refOffset, ref));
break; break;
case WirePointer.FAR: { case WirePointer.FAR: {
segment = segment.getArena().getSegment(FarPointer.getSegmentId(ref)); segment = segment.getArena().getSegment(FarPointer.getSegmentId(ref));
@ -197,13 +198,13 @@ final class WireHelpers {
if (FarPointer.isDoubleFar(ref)) { if (FarPointer.isDoubleFar(ref)) {
SegmentBuilder otherSegment = segment.getArena().getSegment(FarPointer.getSegmentId(ref)); SegmentBuilder otherSegment = segment.getArena().getSegment(FarPointer.getSegmentId(ref));
if (otherSegment.isWritable()) { if (otherSegment.isWritable()) {
zeroObject(otherSegment, padOffset + 1, FarPointer.positionInSegment(pad)); zeroObject(otherSegment, capTable, padOffset + 1, FarPointer.positionInSegment(pad));
} }
segment.buffer.putLong(padOffset * 8, 0L); segment.buffer.putLong(padOffset * 8, 0L);
segment.buffer.putLong((padOffset + 1) * 8, 0L); segment.buffer.putLong((padOffset + 1) * 8, 0L);
} else { } else {
zeroObject(segment, padOffset); zeroObject(segment, capTable, padOffset);
segment.buffer.putLong(padOffset * 8, 0L); segment.buffer.putLong(padOffset * 8, 0L);
} }
} }
@ -211,12 +212,20 @@ final class WireHelpers {
break; break;
} }
case WirePointer.OTHER: { case WirePointer.OTHER: {
// TODO assert WirePointer.isCapability(ref) : "Unknown pointer type";
if (WirePointer.isCapability(ref)) {
var capIndex = WirePointer.upper32Bits(ref);
assert capTable != null: "Cannot zero out capability pointer with no capTable";
if (capTable != null) {
capTable.dropCap(capIndex);
}
}
break;
} }
} }
} }
static void zeroObject(SegmentBuilder segment, long tag, int ptr) { static void zeroObject(SegmentBuilder segment, CapTableBuilder capTable, long tag, int ptr) {
//# We shouldn't zero out external data linked into the message. //# We shouldn't zero out external data linked into the message.
if (!segment.isWritable()) return; if (!segment.isWritable()) return;
@ -225,7 +234,7 @@ final class WireHelpers {
int pointerSection = ptr + StructPointer.dataSize(tag); int pointerSection = ptr + StructPointer.dataSize(tag);
int count = StructPointer.ptrCount(tag); int count = StructPointer.ptrCount(tag);
for (int ii = 0; ii < count; ++ii) { for (int ii = 0; ii < count; ++ii) {
zeroObject(segment, pointerSection + ii); zeroObject(segment, capTable, pointerSection + ii);
} }
memset(segment.buffer, ptr * Constants.BYTES_PER_WORD, (byte)0, memset(segment.buffer, ptr * Constants.BYTES_PER_WORD, (byte)0,
StructPointer.wordSize(tag) * Constants.BYTES_PER_WORD); StructPointer.wordSize(tag) * Constants.BYTES_PER_WORD);
@ -248,7 +257,7 @@ final class WireHelpers {
case ElementSize.POINTER: { case ElementSize.POINTER: {
int count = ListPointer.elementCount(tag); int count = ListPointer.elementCount(tag);
for (int ii = 0; ii < count; ++ii) { for (int ii = 0; ii < count; ++ii) {
zeroObject(segment, ptr + ii); zeroObject(segment, capTable, ptr + ii);
} }
memset(segment.buffer, ptr * Constants.BYTES_PER_WORD, (byte)0, memset(segment.buffer, ptr * Constants.BYTES_PER_WORD, (byte)0,
count * Constants.BYTES_PER_WORD); count * Constants.BYTES_PER_WORD);
@ -267,7 +276,7 @@ final class WireHelpers {
for (int ii = 0; ii < count; ++ii) { for (int ii = 0; ii < count; ++ii) {
pos += dataSize; pos += dataSize;
for (int jj = 0; jj < pointerCount; ++jj) { for (int jj = 0; jj < pointerCount; ++jj) {
zeroObject(segment, pos); zeroObject(segment, capTable, pos);
pos += Constants.POINTER_SIZE_IN_WORDS; pos += Constants.POINTER_SIZE_IN_WORDS;
} }
} }
@ -392,9 +401,17 @@ final class WireHelpers {
int refOffset, int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
StructSize size) { StructSize size) {
AllocateResult allocation = allocate(refOffset, segment, size.total(), WirePointer.STRUCT); return initStructPointer(factory, refOffset, segment, null, size);
}
static <T> T initStructPointer(StructBuilder.Factory<T> factory,
int refOffset,
SegmentBuilder segment,
CapTableBuilder capTable,
StructSize size) {
AllocateResult allocation = allocate(refOffset, segment, capTable, size.total(), WirePointer.STRUCT);
StructPointer.setFromStructSize(allocation.segment.buffer, allocation.refOffset, size); StructPointer.setFromStructSize(allocation.segment.buffer, allocation.refOffset, size);
return factory.constructBuilder(allocation.segment, allocation.ptr * Constants.BYTES_PER_WORD, return factory.constructBuilder(allocation.segment, capTable, allocation.ptr * Constants.BYTES_PER_WORD,
allocation.ptr + size.data, allocation.ptr + size.data,
size.data * 64, size.pointers); size.data * 64, size.pointers);
} }
@ -402,6 +419,7 @@ final class WireHelpers {
static <T> T getWritableStructPointer(StructBuilder.Factory<T> factory, static <T> T getWritableStructPointer(StructBuilder.Factory<T> factory,
int refOffset, int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
CapTableBuilder capTable,
StructSize size, StructSize size,
SegmentReader defaultSegment, SegmentReader defaultSegment,
int defaultOffset) { int defaultOffset) {
@ -409,7 +427,7 @@ final class WireHelpers {
int target = WirePointer.target(refOffset, ref); int target = WirePointer.target(refOffset, ref);
if (WirePointer.isNull(ref)) { if (WirePointer.isNull(ref)) {
if (defaultSegment == null) { if (defaultSegment == null) {
return initStructPointer(factory, refOffset, segment, size); return initStructPointer(factory, refOffset, segment, capTable, size);
} else { } else {
throw new RuntimeException("unimplemented"); throw new RuntimeException("unimplemented");
} }
@ -432,7 +450,7 @@ final class WireHelpers {
//# Don't let allocate() zero out the object just yet. //# Don't let allocate() zero out the object just yet.
zeroPointerAndFars(segment, refOffset); zeroPointerAndFars(segment, refOffset);
AllocateResult allocation = allocate(refOffset, segment, AllocateResult allocation = allocate(refOffset, segment, capTable,
totalSize, WirePointer.STRUCT); totalSize, WirePointer.STRUCT);
StructPointer.set(allocation.segment.buffer, allocation.refOffset, StructPointer.set(allocation.segment.buffer, allocation.refOffset,
@ -458,11 +476,11 @@ final class WireHelpers {
memset(resolved.segment.buffer, resolved.ptr * Constants.BYTES_PER_WORD, (byte)0, memset(resolved.segment.buffer, resolved.ptr * Constants.BYTES_PER_WORD, (byte)0,
(oldDataSize + oldPointerCount * Constants.WORDS_PER_POINTER) * Constants.BYTES_PER_WORD); (oldDataSize + oldPointerCount * Constants.WORDS_PER_POINTER) * Constants.BYTES_PER_WORD);
return factory.constructBuilder(allocation.segment, allocation.ptr * Constants.BYTES_PER_WORD, return factory.constructBuilder(allocation.segment, capTable, allocation.ptr * Constants.BYTES_PER_WORD,
newPointerSection, newDataSize * Constants.BITS_PER_WORD, newPointerSection, newDataSize * Constants.BITS_PER_WORD,
newPointerCount); newPointerCount);
} else { } else {
return factory.constructBuilder(resolved.segment, resolved.ptr * Constants.BYTES_PER_WORD, return factory.constructBuilder(resolved.segment, capTable, resolved.ptr * Constants.BYTES_PER_WORD,
oldPointerSection, oldDataSize * Constants.BITS_PER_WORD, oldPointerSection, oldDataSize * Constants.BITS_PER_WORD,
oldPointerCount); oldPointerCount);
} }
@ -470,6 +488,7 @@ final class WireHelpers {
} }
static <T> T initListPointer(ListBuilder.Factory<T> factory, static <T> T initListPointer(ListBuilder.Factory<T> factory,
CapTableBuilder capTable,
int refOffset, int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
int elementCount, int elementCount,
@ -480,7 +499,7 @@ final class WireHelpers {
int pointerCount = ElementSize.pointersPerElement(elementSize); int pointerCount = ElementSize.pointersPerElement(elementSize);
int step = dataSize + pointerCount * Constants.BITS_PER_POINTER; int step = dataSize + pointerCount * Constants.BITS_PER_POINTER;
int wordCount = roundBitsUpToWords((long)elementCount * (long)step); int wordCount = roundBitsUpToWords((long)elementCount * (long)step);
AllocateResult allocation = allocate(refOffset, segment, wordCount, WirePointer.LIST); AllocateResult allocation = allocate(refOffset, segment, capTable, wordCount, WirePointer.LIST);
ListPointer.set(allocation.segment.buffer, allocation.refOffset, elementSize, elementCount); ListPointer.set(allocation.segment.buffer, allocation.refOffset, elementSize, elementCount);
@ -490,6 +509,7 @@ final class WireHelpers {
} }
static <T> T initStructListPointer(ListBuilder.Factory<T> factory, static <T> T initStructListPointer(ListBuilder.Factory<T> factory,
CapTableBuilder capTable,
int refOffset, int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
int elementCount, int elementCount,
@ -498,7 +518,7 @@ final class WireHelpers {
//# Allocate the list, prefixed by a single WirePointer. //# Allocate the list, prefixed by a single WirePointer.
int wordCount = elementCount * wordsPerElement; int wordCount = elementCount * wordsPerElement;
AllocateResult allocation = allocate(refOffset, segment, Constants.POINTER_SIZE_IN_WORDS + wordCount, AllocateResult allocation = allocate(refOffset, segment, capTable, Constants.POINTER_SIZE_IN_WORDS + wordCount,
WirePointer.LIST); WirePointer.LIST);
//# Initialize the pointer. //# Initialize the pointer.
@ -516,6 +536,7 @@ final class WireHelpers {
static <T> T getWritableListPointer(ListBuilder.Factory<T> factory, static <T> T getWritableListPointer(ListBuilder.Factory<T> factory,
int origRefOffset, int origRefOffset,
SegmentBuilder origSegment, SegmentBuilder origSegment,
CapTableBuilder capTable,
byte elementSize, byte elementSize,
SegmentReader defaultSegment, SegmentReader defaultSegment,
int defaultOffset) { int defaultOffset) {
@ -572,6 +593,7 @@ final class WireHelpers {
} }
static <T> T getWritableStructListPointer(ListBuilder.Factory<T> factory, static <T> T getWritableStructListPointer(ListBuilder.Factory<T> factory,
CapTableBuilder capTable,
int origRefOffset, int origRefOffset,
SegmentBuilder origSegment, SegmentBuilder origSegment,
StructSize elementSize, StructSize elementSize,
@ -624,7 +646,7 @@ final class WireHelpers {
//# Don't let allocate() zero out the object just yet. //# Don't let allocate() zero out the object just yet.
zeroPointerAndFars(origSegment, origRefOffset); zeroPointerAndFars(origSegment, origRefOffset);
AllocateResult allocation = allocate(origRefOffset, origSegment, AllocateResult allocation = allocate(origRefOffset, origSegment, capTable,
totalSize + Constants.POINTER_SIZE_IN_WORDS, totalSize + Constants.POINTER_SIZE_IN_WORDS,
WirePointer.LIST); WirePointer.LIST);
@ -678,7 +700,7 @@ final class WireHelpers {
if (oldSize == ElementSize.VOID) { if (oldSize == ElementSize.VOID) {
//# Nothing to copy, just allocate a new list. //# Nothing to copy, just allocate a new list.
return initStructListPointer(factory, origRefOffset, origSegment, return initStructListPointer(factory, capTable, origRefOffset, origSegment,
elementCount, elementSize); elementCount, elementSize);
} else { } else {
//# Upgrading to an inline composite list. //# Upgrading to an inline composite list.
@ -704,7 +726,7 @@ final class WireHelpers {
//# Don't let allocate() zero out the object just yet. //# Don't let allocate() zero out the object just yet.
zeroPointerAndFars(origSegment, origRefOffset); zeroPointerAndFars(origSegment, origRefOffset);
AllocateResult allocation = allocate(origRefOffset, origSegment, AllocateResult allocation = allocate(origRefOffset, origSegment, capTable,
totalWords + Constants.POINTER_SIZE_IN_WORDS, totalWords + Constants.POINTER_SIZE_IN_WORDS,
WirePointer.LIST); WirePointer.LIST);
@ -754,12 +776,13 @@ final class WireHelpers {
// size is in bytes // size is in bytes
static Text.Builder initTextPointer(int refOffset, static Text.Builder initTextPointer(int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
CapTableBuilder capTable,
int size) { int size) {
//# The byte list must include a NUL terminator. //# The byte list must include a NUL terminator.
int byteSize = size + 1; int byteSize = size + 1;
//# Allocate the space. //# Allocate the space.
AllocateResult allocation = allocate(refOffset, segment, roundBytesUpToWords(byteSize), AllocateResult allocation = allocate(refOffset, segment, capTable, roundBytesUpToWords(byteSize),
WirePointer.LIST); WirePointer.LIST);
//# Initialize the pointer. //# Initialize the pointer.
@ -770,8 +793,9 @@ final class WireHelpers {
static Text.Builder setTextPointer(int refOffset, static Text.Builder setTextPointer(int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
CapTableBuilder capTable,
Text.Reader value) { Text.Reader value) {
Text.Builder builder = initTextPointer(refOffset, segment, value.size); Text.Builder builder = initTextPointer(refOffset, segment, capTable, value.size);
ByteBuffer slice = value.buffer.duplicate(); ByteBuffer slice = value.buffer.duplicate();
slice.position(value.offset); slice.position(value.offset);
@ -783,6 +807,7 @@ final class WireHelpers {
static Text.Builder getWritableTextPointer(int refOffset, static Text.Builder getWritableTextPointer(int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
CapTableBuilder capTable,
ByteBuffer defaultBuffer, ByteBuffer defaultBuffer,
int defaultOffset, int defaultOffset,
int defaultSize) { int defaultSize) {
@ -792,7 +817,7 @@ final class WireHelpers {
if (defaultBuffer == null) { if (defaultBuffer == null) {
return new Text.Builder(); return new Text.Builder();
} else { } else {
Text.Builder builder = initTextPointer(refOffset, segment, defaultSize); Text.Builder builder = initTextPointer(refOffset, segment, capTable, defaultSize);
// TODO is there a way to do this with bulk methods? // TODO is there a way to do this with bulk methods?
for (int i = 0; i < builder.size; ++i) { for (int i = 0; i < builder.size; ++i) {
builder.buffer.put(builder.offset + i, defaultBuffer.get(defaultOffset * 8 + i)); builder.buffer.put(builder.offset + i, defaultBuffer.get(defaultOffset * 8 + i));
@ -826,9 +851,10 @@ final class WireHelpers {
// size is in bytes // size is in bytes
static Data.Builder initDataPointer(int refOffset, static Data.Builder initDataPointer(int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
CapTableBuilder capTable,
int size) { int size) {
//# Allocate the space. //# Allocate the space.
AllocateResult allocation = allocate(refOffset, segment, roundBytesUpToWords(size), AllocateResult allocation = allocate(refOffset, segment, capTable, roundBytesUpToWords(size),
WirePointer.LIST); WirePointer.LIST);
//# Initialize the pointer. //# Initialize the pointer.
@ -839,8 +865,9 @@ final class WireHelpers {
static Data.Builder setDataPointer(int refOffset, static Data.Builder setDataPointer(int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
CapTableBuilder capTable,
Data.Reader value) { Data.Reader value) {
Data.Builder builder = initDataPointer(refOffset, segment, value.size); Data.Builder builder = initDataPointer(refOffset, segment, capTable, value.size);
// TODO is there a way to do this with bulk methods? // TODO is there a way to do this with bulk methods?
for (int i = 0; i < builder.size; ++i) { for (int i = 0; i < builder.size; ++i) {
@ -851,6 +878,7 @@ final class WireHelpers {
static Data.Builder getWritableDataPointer(int refOffset, static Data.Builder getWritableDataPointer(int refOffset,
SegmentBuilder segment, SegmentBuilder segment,
CapTableBuilder capTable,
ByteBuffer defaultBuffer, ByteBuffer defaultBuffer,
int defaultOffset, int defaultOffset,
int defaultSize) { int defaultSize) {
@ -860,7 +888,7 @@ final class WireHelpers {
if (defaultBuffer == null) { if (defaultBuffer == null) {
return new Data.Builder(); return new Data.Builder();
} else { } else {
Data.Builder builder = initDataPointer(refOffset, segment, defaultSize); Data.Builder builder = initDataPointer(refOffset, segment, capTable, defaultSize);
// TODO is there a way to do this with bulk methods? // TODO is there a way to do this with bulk methods?
for (int i = 0; i < builder.size; ++i) { for (int i = 0; i < builder.size; ++i) {
builder.buffer.put(builder.offset + i, defaultBuffer.get(defaultOffset * 8 + i)); builder.buffer.put(builder.offset + i, defaultBuffer.get(defaultOffset * 8 + i));
@ -887,6 +915,7 @@ final class WireHelpers {
static <T> T readStructPointer(StructReader.Factory<T> factory, static <T> T readStructPointer(StructReader.Factory<T> factory,
SegmentReader segment, SegmentReader segment,
CapTableReader capTable,
int refOffset, int refOffset,
SegmentReader defaultSegment, SegmentReader defaultSegment,
int defaultOffset, int defaultOffset,
@ -918,6 +947,7 @@ final class WireHelpers {
resolved.segment.arena.checkReadLimit(StructPointer.wordSize(resolved.ref)); resolved.segment.arena.checkReadLimit(StructPointer.wordSize(resolved.ref));
return factory.constructReader(resolved.segment, return factory.constructReader(resolved.segment,
capTable,
resolved.ptr * Constants.BYTES_PER_WORD, resolved.ptr * Constants.BYTES_PER_WORD,
(resolved.ptr + dataSizeWords), (resolved.ptr + dataSizeWords),
dataSizeWords * Constants.BITS_PER_WORD, dataSizeWords * Constants.BITS_PER_WORD,
@ -926,11 +956,11 @@ final class WireHelpers {
} }
static SegmentBuilder setStructPointer(SegmentBuilder segment, int refOffset, StructReader value) { static SegmentBuilder setStructPointer(SegmentBuilder segment, CapTableBuilder capTable, int refOffset, StructReader value) {
short dataSize = (short)roundBitsUpToWords(value.dataSize); short dataSize = (short)roundBitsUpToWords(value.dataSize);
int totalSize = dataSize + value.pointerCount * Constants.POINTER_SIZE_IN_WORDS; int totalSize = dataSize + value.pointerCount * Constants.POINTER_SIZE_IN_WORDS;
AllocateResult allocation = allocate(refOffset, segment, totalSize, WirePointer.STRUCT); AllocateResult allocation = allocate(refOffset, segment, capTable, totalSize, WirePointer.STRUCT);
StructPointer.set(allocation.segment.buffer, allocation.refOffset, StructPointer.set(allocation.segment.buffer, allocation.refOffset,
dataSize, value.pointerCount); dataSize, value.pointerCount);
@ -943,25 +973,25 @@ final class WireHelpers {
int pointerSection = allocation.ptr + dataSize; int pointerSection = allocation.ptr + dataSize;
for (int i = 0; i < value.pointerCount; ++i) { for (int i = 0; i < value.pointerCount; ++i) {
copyPointer(allocation.segment, pointerSection + i, value.segment, value.pointers + i, copyPointer(allocation.segment, capTable, pointerSection + i, value.segment, value.capTable, value.pointers + i,
value.nestingLimit); value.nestingLimit);
} }
return allocation.segment; return allocation.segment;
}; };
static SegmentBuilder setListPointer(SegmentBuilder segment, int refOffset, ListReader value) { static SegmentBuilder setListPointer(SegmentBuilder segment, CapTableBuilder capTable, int refOffset, ListReader value) {
int totalSize = roundBitsUpToWords(value.elementCount * value.step); int totalSize = roundBitsUpToWords(value.elementCount * value.step);
if (value.step <= Constants.BITS_PER_WORD) { if (value.step <= Constants.BITS_PER_WORD) {
//# List of non-structs. //# List of non-structs.
AllocateResult allocation = allocate(refOffset, segment, totalSize, WirePointer.LIST); AllocateResult allocation = allocate(refOffset, segment, capTable, totalSize, WirePointer.LIST);
if (value.structPointerCount == 1) { if (value.structPointerCount == 1) {
//# List of pointers. //# List of pointers.
ListPointer.set(allocation.segment.buffer, allocation.refOffset, ElementSize.POINTER, value.elementCount); ListPointer.set(allocation.segment.buffer, allocation.refOffset, ElementSize.POINTER, value.elementCount);
for (int i = 0; i < value.elementCount; ++i) { for (int i = 0; i < value.elementCount; ++i) {
copyPointer(allocation.segment, allocation.ptr + i, copyPointer(allocation.segment, capTable,allocation.ptr + i,
value.segment, value.ptr / Constants.BYTES_PER_WORD + i, value.nestingLimit); value.segment, value.capTable, value.ptr / Constants.BYTES_PER_WORD + i, value.nestingLimit);
} }
} else { } else {
//# List of data. //# List of data.
@ -984,7 +1014,7 @@ final class WireHelpers {
return allocation.segment; return allocation.segment;
} else { } else {
//# List of structs. //# List of structs.
AllocateResult allocation = allocate(refOffset, segment, totalSize + Constants.POINTER_SIZE_IN_WORDS, WirePointer.LIST); AllocateResult allocation = allocate(refOffset, segment, capTable, totalSize + Constants.POINTER_SIZE_IN_WORDS, WirePointer.LIST);
ListPointer.setInlineComposite(allocation.segment.buffer, allocation.refOffset, totalSize); ListPointer.setInlineComposite(allocation.segment.buffer, allocation.refOffset, totalSize);
short dataSize = (short)roundBitsUpToWords(value.structDataSize); short dataSize = (short)roundBitsUpToWords(value.structDataSize);
short pointerCount = value.structPointerCount; short pointerCount = value.structPointerCount;
@ -1005,7 +1035,7 @@ final class WireHelpers {
srcOffset += dataSize; srcOffset += dataSize;
for (int j = 0; j < pointerCount; ++j) { for (int j = 0; j < pointerCount; ++j) {
copyPointer(allocation.segment, dstOffset, value.segment, srcOffset, value.nestingLimit); copyPointer(allocation.segment, capTable, dstOffset, value.segment, value.capTable, srcOffset, value.nestingLimit);
dstOffset += Constants.POINTER_SIZE_IN_WORDS; dstOffset += Constants.POINTER_SIZE_IN_WORDS;
srcOffset += Constants.POINTER_SIZE_IN_WORDS; srcOffset += Constants.POINTER_SIZE_IN_WORDS;
} }
@ -1031,8 +1061,8 @@ final class WireHelpers {
dstDup.put(srcDup); dstDup.put(srcDup);
} }
static SegmentBuilder copyPointer(SegmentBuilder dstSegment, int dstOffset, static SegmentBuilder copyPointer(SegmentBuilder dstSegment, CapTableBuilder dstCapTable, int dstOffset,
SegmentReader srcSegment, int srcOffset, int nestingLimit) { SegmentReader srcSegment, CapTableReader srcCapTable, int srcOffset, int nestingLimit) {
// Deep-copy the object pointed to by src into dst. It turns out we can't reuse // Deep-copy the object pointed to by src into dst. It turns out we can't reuse
// readStructPointer(), etc. because they do type checking whereas here we want to accept any // readStructPointer(), etc. because they do type checking whereas here we want to accept any
// valid pointer. // valid pointer.
@ -1053,7 +1083,7 @@ final class WireHelpers {
throw new DecodeException("Message is too deeply nested or contains cycles. See org.capnproto.ReaderOptions."); throw new DecodeException("Message is too deeply nested or contains cycles. See org.capnproto.ReaderOptions.");
} }
resolved.segment.arena.checkReadLimit(StructPointer.wordSize(resolved.ref)); resolved.segment.arena.checkReadLimit(StructPointer.wordSize(resolved.ref));
return setStructPointer(dstSegment, dstOffset, return setStructPointer(dstSegment, dstCapTable, dstOffset,
new StructReader(resolved.segment, new StructReader(resolved.segment,
resolved.ptr * Constants.BYTES_PER_WORD, resolved.ptr * Constants.BYTES_PER_WORD,
resolved.ptr + StructPointer.dataSize(resolved.ref), resolved.ptr + StructPointer.dataSize(resolved.ref),
@ -1088,7 +1118,7 @@ final class WireHelpers {
resolved.segment.arena.checkReadLimit(elementCount); resolved.segment.arena.checkReadLimit(elementCount);
} }
return setListPointer(dstSegment, dstOffset, return setListPointer(dstSegment, dstCapTable, dstOffset,
new ListReader(resolved.segment, new ListReader(resolved.segment,
ptr * Constants.BYTES_PER_WORD, ptr * Constants.BYTES_PER_WORD,
elementCount, elementCount,
@ -1111,7 +1141,7 @@ final class WireHelpers {
resolved.segment.arena.checkReadLimit(elementCount); resolved.segment.arena.checkReadLimit(elementCount);
} }
return setListPointer(dstSegment, dstOffset, return setListPointer(dstSegment, dstCapTable, dstOffset,
new ListReader(resolved.segment, new ListReader(resolved.segment,
resolved.ptr * Constants.BYTES_PER_WORD, resolved.ptr * Constants.BYTES_PER_WORD,
elementCount, elementCount,
@ -1132,6 +1162,7 @@ final class WireHelpers {
static <T> T readListPointer(ListReader.Factory<T> factory, static <T> T readListPointer(ListReader.Factory<T> factory,
SegmentReader segment, SegmentReader segment,
int refOffset, int refOffset,
CapTableReader capTable,
SegmentReader defaultSegment, SegmentReader defaultSegment,
int defaultOffset, int defaultOffset,
byte expectedElementSize, byte expectedElementSize,
@ -1316,16 +1347,19 @@ final class WireHelpers {
long ref = segment.get(refOffset); long ref = segment.get(refOffset);
if (!WirePointer.isNull(ref)) { if (!WirePointer.isNull(ref)) {
zeroObject(segment, refOffset); zeroObject(segment, capTable, refOffset);
} }
if (cap == null) { if (cap == null) {
// TODO check zeroMemory behaviour // TODO check zeroMemory behaviour
zeroPointerAndFars(segment, refOffset); zeroPointerAndFars(segment, refOffset);
} }
else { else if (capTable != null) {
WirePointer.setCap(segment.buffer, refOffset, capTable.injectCap(cap)); WirePointer.setCap(segment.buffer, refOffset, capTable.injectCap(cap));
} }
else {
assert false: "Cannot set capability pointer without capTable";
}
} }
static ClientHook readCapabilityPointer(SegmentReader segment, CapTableReader capTable, int refOffset, int maxValue) { static ClientHook readCapabilityPointer(SegmentReader segment, CapTableReader capTable, int refOffset, int maxValue) {
@ -1339,6 +1373,10 @@ final class WireHelpers {
return Capability.newBrokenCap("Calling capability extracted from a non-capability pointer."); return Capability.newBrokenCap("Calling capability extracted from a non-capability pointer.");
} }
if (capTable == null) {
return Capability.newBrokenCap("Cannot read capability pointer without capTable.");
}
var cap = capTable.extractCap(WirePointer.upper32Bits(ref)); var cap = capTable.extractCap(WirePointer.upper32Bits(ref));
if (cap == null) { if (cap == null) {
return Capability.newBrokenCap("Calling invalid capability pointer."); return Capability.newBrokenCap("Calling invalid capability pointer.");

View file

@ -25,7 +25,7 @@ public class LayoutTest {
ReaderArena arena = new ReaderArena(new ByteBuffer[]{ buffer }, 0x7fffffffffffffffL); ReaderArena arena = new ReaderArena(new ByteBuffer[]{ buffer }, 0x7fffffffffffffffL);
StructReader reader = WireHelpers.readStructPointer(new BareStructReader(), arena.tryGetSegment(0), 0, null, 0, 0x7fffffff); StructReader reader = WireHelpers.readStructPointer(new BareStructReader(), arena.tryGetSegment(0), null,0, null, 0, 0x7fffffff);
Assert.assertEquals(reader._getLongField(0), 0xefcdab8967452301L); Assert.assertEquals(reader._getLongField(0), 0xefcdab8967452301L);
Assert.assertEquals(reader._getLongField(1), 0L); Assert.assertEquals(reader._getLongField(1), 0L);

View file

@ -22,7 +22,7 @@ class TestCap0 {
public Client(ClientHook hook) { super(hook); } public Client(ClientHook hook) { super(hook); }
public Client(Capability.Client cap) { super(cap.getHook()); } public Client(Capability.Client cap) { super(cap.hook); }
public Client(Capability.Server server) { super(server); } public Client(Capability.Server server) { super(server); }
@ -85,7 +85,7 @@ class TestCap1 {
public Client(ClientHook hook) { super(hook); } public Client(ClientHook hook) { super(hook); }
public Client(Capability.Client cap) { super(cap.getHook()); } public Client(Capability.Client cap) { super(cap.hook); }
public Client(Capability.Server server) { super(server); } public Client(Capability.Server server) { super(server); }
} }
@ -111,7 +111,8 @@ class TestCap1 {
class TestCap0Impl extends TestCap0.Server { class TestCap0Impl extends TestCap0.Server {
final TestCap1.Client testCap1 = new TestCap1.Client(new TestCap1Impl()); final TestCap1.Client testCap1a = new TestCap1.Client(new TestCap1Impl());
final TestCap1.Client testCap1b = new TestCap1.Client(new TestCap1Impl());
public CompletableFuture<?> testMethod0(TestCap0.Server.TestMethod0Context ctx) { public CompletableFuture<?> testMethod0(TestCap0.Server.TestMethod0Context ctx) {
var params = ctx.getParams(); var params = ctx.getParams();
@ -124,7 +125,11 @@ class TestCap0Impl extends TestCap0.Server {
var params = ctx.getParams(); var params = ctx.getParams();
var results = ctx.getResults(); var results = ctx.getResults();
var res0 = results.getResult0(); var res0 = results.getResult0();
res0.setAsCapability(testCap1); res0.setAsCapability(testCap1a);
var res1 = results.getResult1();
res1.setAsCapability(testCap1b);
var res2 = results.getResult2();
res2.setAsCapability(testCap1b);
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
} }
@ -195,12 +200,19 @@ public class TwoPartyTest {
var params = request.params(); var params = request.params();
var resultsPromise = request.send(); var resultsPromise = request.send();
while (!resultsPromise.isDone()) { while (!resultsPromise.isDone()) {
CompletableFuture.anyOf(resultsPromise, server.runOnce()).join(); CompletableFuture.anyOf(resultsPromise, server.runOnce(), client.runOnce()).join();
} }
Assert.assertTrue(resultsPromise.isDone()); Assert.assertTrue(resultsPromise.isDone());
var results = resultsPromise.get(); var results = resultsPromise.get();
var any = results.getResult0(); var cap0 = results.getResult0().getAsCapability();
var cap1 = any.getAsCapability(); Assert.assertFalse(cap0.hook.isNull());
Assert.assertFalse(cap0.hook.isError());
var cap1 = results.getResult1().getAsCapability();
Assert.assertFalse(cap1.hook.isNull());
Assert.assertFalse(cap1.hook.isError());
var cap2 = results.getResult2().getAsCapability();
Assert.assertFalse(cap2.hook.isNull());
Assert.assertFalse(cap2.hook.isError());
} }
@Test @Test

View file

@ -166,7 +166,7 @@ public final class Demo {
public static class TestResults1 { public static class TestResults1 {
public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)0,(short)1); public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)0,(short)3);
public static final class Factory extends org.capnproto.StructFactory<Builder, Reader> { public static final class Factory extends org.capnproto.StructFactory<Builder, Reader> {
public Factory() { public Factory() {
} }
@ -206,6 +206,32 @@ public final class Demo {
return _initPointerField(org.capnproto.AnyPointer.factory, 0, size); return _initPointerField(org.capnproto.AnyPointer.factory, 0, size);
} }
public final boolean hasResult1() {
return !_pointerFieldIsNull(1);
}
public org.capnproto.AnyPointer.Builder getResult1() {
return _getPointerField(org.capnproto.AnyPointer.factory, 1);
}
public org.capnproto.AnyPointer.Builder initResult1() {
return _initPointerField(org.capnproto.AnyPointer.factory, 1, 0);
}
public org.capnproto.AnyPointer.Builder initResult1(int size) {
return _initPointerField(org.capnproto.AnyPointer.factory, 1, size);
}
public final boolean hasResult2() {
return !_pointerFieldIsNull(2);
}
public org.capnproto.AnyPointer.Builder getResult2() {
return _getPointerField(org.capnproto.AnyPointer.factory, 2);
}
public org.capnproto.AnyPointer.Builder initResult2() {
return _initPointerField(org.capnproto.AnyPointer.factory, 2, 0);
}
public org.capnproto.AnyPointer.Builder initResult2(int size) {
return _initPointerField(org.capnproto.AnyPointer.factory, 2, size);
}
} }
public static final class Reader extends org.capnproto.StructReader { public static final class Reader extends org.capnproto.StructReader {
@ -219,6 +245,18 @@ public final class Demo {
public org.capnproto.AnyPointer.Reader getResult0() { public org.capnproto.AnyPointer.Reader getResult0() {
return _getPointerField(org.capnproto.AnyPointer.factory, 0); return _getPointerField(org.capnproto.AnyPointer.factory, 0);
} }
public boolean hasResult1() {
return !_pointerFieldIsNull(1);
}
public org.capnproto.AnyPointer.Reader getResult1() {
return _getPointerField(org.capnproto.AnyPointer.factory, 1);
}
public boolean hasResult2() {
return !_pointerFieldIsNull(2);
}
public org.capnproto.AnyPointer.Reader getResult2() {
return _getPointerField(org.capnproto.AnyPointer.factory, 2);
}
} }
} }
@ -230,20 +268,25 @@ public static final org.capnproto.SegmentReader b_b301b4acd180f012 =
org.capnproto.GeneratedClassSupport.decodeRawBytes( org.capnproto.GeneratedClassSupport.decodeRawBytes(
"\u0000\u0000\u0000\u0000\u0005\u0000\u0006\u0000" + "\u0000\u0000\u0000\u0000\u0005\u0000\u0006\u0000" +
"\u0012\u00f0\u0080\u00d1\u00ac\u00b4\u0001\u00b3" + "\u0012\u00f0\u0080\u00d1\u00ac\u00b4\u0001\u00b3" +
"\u0011\u0000\u0000\u0000\u0001\u0000\u0001\u0000" + "\u003a\u0000\u0000\u0000\u0001\u0000\u0001\u0000" +
"\u00c4\u0053\u0042\u00d6\u0097\u0077\u00b5\u0091" + "\u00c4\u0053\u0042\u00d6\u0097\u0077\u00b5\u0091" +
"\u0000\u0000\u0007\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0007\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0015\u0000\u0000\u0000\u00ea\u0000\u0000\u0000" + "\u0015\u0000\u0000\u0000\u0032\u0002\u0000\u0000" +
"\u0021\u0000\u0000\u0000\u0007\u0000\u0000\u0000" + "\u0035\u0000\u0000\u0000\u0007\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u001d\u0000\u0000\u0000\u003f\u0000\u0000\u0000" + "\u0031\u0000\u0000\u0000\u003f\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0064\u0065\u006d\u006f\u0070\u0061\u0072\u0061" + "\u0072\u0075\u006e\u0074\u0069\u006d\u0065\u002f" +
"\u006d\u0073\u002e\u0063\u0061\u0070\u006e\u0070" + "\u0073\u0072\u0063\u002f\u0074\u0065\u0073\u0074" +
"\u003a\u0054\u0065\u0073\u0074\u0050\u0061\u0072" + "\u002f\u006a\u0061\u0076\u0061\u002f\u006f\u0072" +
"\u0061\u006d\u0073\u0030\u0000\u0000\u0000\u0000" + "\u0067\u002f\u0063\u0061\u0070\u006e\u0070\u0072" +
"\u006f\u0074\u006f\u002f\u0064\u0065\u006d\u006f" +
"\u002f\u0064\u0065\u006d\u006f\u0070\u0061\u0072" +
"\u0061\u006d\u0073\u002e\u0063\u0061\u0070\u006e" +
"\u0070\u003a\u0054\u0065\u0073\u0074\u0050\u0061" +
"\u0072\u0061\u006d\u0073\u0030\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000" + "\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000" +
"\u0004\u0000\u0000\u0000\u0003\u0000\u0004\u0000" + "\u0004\u0000\u0000\u0000\u0003\u0000\u0004\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
@ -265,20 +308,25 @@ public static final org.capnproto.SegmentReader b_96a42e5421b52881 =
org.capnproto.GeneratedClassSupport.decodeRawBytes( org.capnproto.GeneratedClassSupport.decodeRawBytes(
"\u0000\u0000\u0000\u0000\u0005\u0000\u0006\u0000" + "\u0000\u0000\u0000\u0000\u0005\u0000\u0006\u0000" +
"\u0081\u0028\u00b5\u0021\u0054\u002e\u00a4\u0096" + "\u0081\u0028\u00b5\u0021\u0054\u002e\u00a4\u0096" +
"\u0011\u0000\u0000\u0000\u0001\u0000\u0001\u0000" + "\u003a\u0000\u0000\u0000\u0001\u0000\u0001\u0000" +
"\u00c4\u0053\u0042\u00d6\u0097\u0077\u00b5\u0091" + "\u00c4\u0053\u0042\u00d6\u0097\u0077\u00b5\u0091" +
"\u0000\u0000\u0007\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0007\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0015\u0000\u0000\u0000\u00f2\u0000\u0000\u0000" + "\u0015\u0000\u0000\u0000\u003a\u0002\u0000\u0000" +
"\u0021\u0000\u0000\u0000\u0007\u0000\u0000\u0000" + "\u0035\u0000\u0000\u0000\u0007\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u001d\u0000\u0000\u0000\u003f\u0000\u0000\u0000" + "\u0031\u0000\u0000\u0000\u003f\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0064\u0065\u006d\u006f\u0070\u0061\u0072\u0061" + "\u0072\u0075\u006e\u0074\u0069\u006d\u0065\u002f" +
"\u006d\u0073\u002e\u0063\u0061\u0070\u006e\u0070" + "\u0073\u0072\u0063\u002f\u0074\u0065\u0073\u0074" +
"\u003a\u0054\u0065\u0073\u0074\u0052\u0065\u0073" + "\u002f\u006a\u0061\u0076\u0061\u002f\u006f\u0072" +
"\u0075\u006c\u0074\u0073\u0030\u0000\u0000\u0000" + "\u0067\u002f\u0063\u0061\u0070\u006e\u0070\u0072" +
"\u006f\u0074\u006f\u002f\u0064\u0065\u006d\u006f" +
"\u002f\u0064\u0065\u006d\u006f\u0070\u0061\u0072" +
"\u0061\u006d\u0073\u002e\u0063\u0061\u0070\u006e" +
"\u0070\u003a\u0054\u0065\u0073\u0074\u0052\u0065" +
"\u0073\u0075\u006c\u0074\u0073\u0030\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000" + "\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000" +
"\u0004\u0000\u0000\u0000\u0003\u0000\u0004\u0000" + "\u0004\u0000\u0000\u0000\u0003\u0000\u0004\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
@ -300,20 +348,25 @@ public static final org.capnproto.SegmentReader b_e10363a8b6220957 =
org.capnproto.GeneratedClassSupport.decodeRawBytes( org.capnproto.GeneratedClassSupport.decodeRawBytes(
"\u0000\u0000\u0000\u0000\u0005\u0000\u0006\u0000" + "\u0000\u0000\u0000\u0000\u0005\u0000\u0006\u0000" +
"\u0057\u0009\"\u00b6\u00a8\u0063\u0003\u00e1" + "\u0057\u0009\"\u00b6\u00a8\u0063\u0003\u00e1" +
"\u0011\u0000\u0000\u0000\u0001\u0000\u0000\u0000" + "\u003a\u0000\u0000\u0000\u0001\u0000\u0000\u0000" +
"\u00c4\u0053\u0042\u00d6\u0097\u0077\u00b5\u0091" + "\u00c4\u0053\u0042\u00d6\u0097\u0077\u00b5\u0091" +
"\u0001\u0000\u0007\u0000\u0000\u0000\u0000\u0000" + "\u0001\u0000\u0007\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0015\u0000\u0000\u0000\u00ea\u0000\u0000\u0000" + "\u0015\u0000\u0000\u0000\u0032\u0002\u0000\u0000" +
"\u0021\u0000\u0000\u0000\u0007\u0000\u0000\u0000" + "\u0035\u0000\u0000\u0000\u0007\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u001d\u0000\u0000\u0000\u003f\u0000\u0000\u0000" + "\u0031\u0000\u0000\u0000\u003f\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0064\u0065\u006d\u006f\u0070\u0061\u0072\u0061" + "\u0072\u0075\u006e\u0074\u0069\u006d\u0065\u002f" +
"\u006d\u0073\u002e\u0063\u0061\u0070\u006e\u0070" + "\u0073\u0072\u0063\u002f\u0074\u0065\u0073\u0074" +
"\u003a\u0054\u0065\u0073\u0074\u0050\u0061\u0072" + "\u002f\u006a\u0061\u0076\u0061\u002f\u006f\u0072" +
"\u0061\u006d\u0073\u0031\u0000\u0000\u0000\u0000" + "\u0067\u002f\u0063\u0061\u0070\u006e\u0070\u0072" +
"\u006f\u0074\u006f\u002f\u0064\u0065\u006d\u006f" +
"\u002f\u0064\u0065\u006d\u006f\u0070\u0061\u0072" +
"\u0061\u006d\u0073\u002e\u0063\u0061\u0070\u006e" +
"\u0070\u003a\u0054\u0065\u0073\u0074\u0050\u0061" +
"\u0072\u0061\u006d\u0073\u0031\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000" + "\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000" +
"\u0004\u0000\u0000\u0000\u0003\u0000\u0004\u0000" + "\u0004\u0000\u0000\u0000\u0003\u0000\u0004\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
@ -335,29 +388,48 @@ public static final org.capnproto.SegmentReader b_99852ee4d45ddb3e =
org.capnproto.GeneratedClassSupport.decodeRawBytes( org.capnproto.GeneratedClassSupport.decodeRawBytes(
"\u0000\u0000\u0000\u0000\u0005\u0000\u0006\u0000" + "\u0000\u0000\u0000\u0000\u0005\u0000\u0006\u0000" +
"\u003e\u00db\u005d\u00d4\u00e4\u002e\u0085\u0099" + "\u003e\u00db\u005d\u00d4\u00e4\u002e\u0085\u0099" +
"\u0011\u0000\u0000\u0000\u0001\u0000\u0000\u0000" + "\u003a\u0000\u0000\u0000\u0001\u0000\u0000\u0000" +
"\u00c4\u0053\u0042\u00d6\u0097\u0077\u00b5\u0091" + "\u00c4\u0053\u0042\u00d6\u0097\u0077\u00b5\u0091" +
"\u0001\u0000\u0007\u0000\u0000\u0000\u0000\u0000" + "\u0003\u0000\u0007\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0015\u0000\u0000\u0000\u00f2\u0000\u0000\u0000" + "\u0015\u0000\u0000\u0000\u003a\u0002\u0000\u0000" +
"\u0021\u0000\u0000\u0000\u0007\u0000\u0000\u0000" + "\u0035\u0000\u0000\u0000\u0007\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u001d\u0000\u0000\u0000\u003f\u0000\u0000\u0000" + "\u0031\u0000\u0000\u0000\u00af\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0064\u0065\u006d\u006f\u0070\u0061\u0072\u0061" + "\u0072\u0075\u006e\u0074\u0069\u006d\u0065\u002f" +
"\u006d\u0073\u002e\u0063\u0061\u0070\u006e\u0070" + "\u0073\u0072\u0063\u002f\u0074\u0065\u0073\u0074" +
"\u003a\u0054\u0065\u0073\u0074\u0052\u0065\u0073" + "\u002f\u006a\u0061\u0076\u0061\u002f\u006f\u0072" +
"\u0075\u006c\u0074\u0073\u0031\u0000\u0000\u0000" + "\u0067\u002f\u0063\u0061\u0070\u006e\u0070\u0072" +
"\u006f\u0074\u006f\u002f\u0064\u0065\u006d\u006f" +
"\u002f\u0064\u0065\u006d\u006f\u0070\u0061\u0072" +
"\u0061\u006d\u0073\u002e\u0063\u0061\u0070\u006e" +
"\u0070\u003a\u0054\u0065\u0073\u0074\u0052\u0065" +
"\u0073\u0075\u006c\u0074\u0073\u0031\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000" + "\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000" +
"\u0004\u0000\u0000\u0000\u0003\u0000\u0004\u0000" + "\u000c\u0000\u0000\u0000\u0003\u0000\u0004\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0001\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0001\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\r\u0000\u0000\u0000\u0042\u0000\u0000\u0000" + "\u0045\u0000\u0000\u0000\u0042\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0008\u0000\u0000\u0000\u0003\u0000\u0001\u0000" + "\u0040\u0000\u0000\u0000\u0003\u0000\u0001\u0000" +
"\u0014\u0000\u0000\u0000\u0002\u0000\u0001\u0000" + "\u004c\u0000\u0000\u0000\u0002\u0000\u0001\u0000" +
"\u0001\u0000\u0000\u0000\u0001\u0000\u0000\u0000" +
"\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0049\u0000\u0000\u0000\u0042\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0044\u0000\u0000\u0000\u0003\u0000\u0001\u0000" +
"\u0050\u0000\u0000\u0000\u0002\u0000\u0001\u0000" +
"\u0002\u0000\u0000\u0000\u0002\u0000\u0000\u0000" +
"\u0000\u0000\u0001\u0000\u0002\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u004d\u0000\u0000\u0000\u0042\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0048\u0000\u0000\u0000\u0003\u0000\u0001\u0000" +
"\u0054\u0000\u0000\u0000\u0002\u0000\u0001\u0000" +
"\u0072\u0065\u0073\u0075\u006c\u0074\u0030\u0000" + "\u0072\u0065\u0073\u0075\u006c\u0074\u0030\u0000" +
"\u0012\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0012\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
@ -365,6 +437,22 @@ public static final org.capnproto.SegmentReader b_99852ee4d45ddb3e =
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0012\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0012\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0072\u0065\u0073\u0075\u006c\u0074\u0031\u0000" +
"\u0012\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0012\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0072\u0065\u0073\u0075\u006c\u0074\u0032\u0000" +
"\u0012\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0012\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" +
"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + ""); "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000" + "");
} }
} }

View file

@ -18,6 +18,8 @@ struct TestParams1 {
struct TestResults1 { struct TestResults1 {
result0 @0 :AnyPointer; result0 @0 :AnyPointer;
result1 @1 :AnyPointer;
result2 @2 :AnyPointer;
} }