diff --git a/runtime/src/main/java/org/capnproto/AnyPointer.java b/runtime/src/main/java/org/capnproto/AnyPointer.java index a101cde..c7ba1ec 100644 --- a/runtime/src/main/java/org/capnproto/AnyPointer.java +++ b/runtime/src/main/java/org/capnproto/AnyPointer.java @@ -9,9 +9,21 @@ public final class AnyPointer { this.reader = reader; } - public T getAsStruct(FromStructReader factory) { + public final T getAsStruct(FromStructReader factory) { return factory.fromStructReader(this.reader.getStruct()); } } + public static final class Builder { + public final PointerBuilder builder; + + public Builder(PointerBuilder builder) { + this.builder = builder; + } + + public final T initAsStruct(FromStructBuilder factory) { + return factory.fromStructBuilder(this.builder.initStruct(factory.structSize())); + } + } + } diff --git a/runtime/src/main/java/org/capnproto/Arena.java b/runtime/src/main/java/org/capnproto/Arena.java new file mode 100644 index 0000000..01dce98 --- /dev/null +++ b/runtime/src/main/java/org/capnproto/Arena.java @@ -0,0 +1,5 @@ +package org.capnproto; + +public interface Arena { + public SegmentReader tryGetSegment(int id); +} diff --git a/runtime/src/main/java/org/capnproto/BuilderArena.java b/runtime/src/main/java/org/capnproto/BuilderArena.java new file mode 100644 index 0000000..294462a --- /dev/null +++ b/runtime/src/main/java/org/capnproto/BuilderArena.java @@ -0,0 +1,36 @@ +package org.capnproto; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Vector; + +public final class BuilderArena implements Arena { + public final Vector segments; + + public BuilderArena() { + this.segments = new Vector(); + SegmentBuilder segment0 = new SegmentBuilder(ByteBuffer.allocate(1024 * 8)); + segment0.buffer.mark(); + this.segments.add(segment0); + } + + public SegmentReader tryGetSegment(int id) { + throw new Error("unimplemented"); + } + public SegmentBuilder getSegment(int id) { + throw new Error("unimplemented"); + } + + public static class AllocateResult { + public final SegmentBuilder segment; + public final int offset; + public AllocateResult(SegmentBuilder segment, int offset) { + this.segment = segment; + this.offset = offset; + } + } + + public AllocateResult allocate(int amount) { + throw new Error("unimplemented"); + } +} diff --git a/runtime/src/main/java/org/capnproto/MessageBuilder.java b/runtime/src/main/java/org/capnproto/MessageBuilder.java index d54e9b8..6d8a4cb 100644 --- a/runtime/src/main/java/org/capnproto/MessageBuilder.java +++ b/runtime/src/main/java/org/capnproto/MessageBuilder.java @@ -1,11 +1,25 @@ package org.capnproto; public final class MessageBuilder { + + private final BuilderArena arena; + + public MessageBuilder() { + this.arena = new BuilderArena(); + } + public T getRoot(FromStructBuilder factory) { throw new Error("unimplemented"); } public T initRoot(FromStructBuilder factory) { - throw new Error("unimplemented"); + SegmentBuilder rootSegment = this.arena.segments.get(0); + int location = rootSegment.allocate(1); + if (location == SegmentBuilder.FAILED_ALLOCATION) { + throw new Error("could not allocate root pointer"); + } + + AnyPointer.Builder ptr = new AnyPointer.Builder(PointerBuilder.getRoot(rootSegment, location)); + return ptr.initAsStruct(factory); } } diff --git a/runtime/src/main/java/org/capnproto/PointerBuilder.java b/runtime/src/main/java/org/capnproto/PointerBuilder.java index 5f583c2..4f40d24 100644 --- a/runtime/src/main/java/org/capnproto/PointerBuilder.java +++ b/runtime/src/main/java/org/capnproto/PointerBuilder.java @@ -9,10 +9,18 @@ public final class PointerBuilder { this.pointer = pointer; } + public static PointerBuilder getRoot(SegmentBuilder segment, int location) { + return new PointerBuilder(segment, location); + } + public final boolean isNull() { return this.segment.buffer.getLong(this.pointer) == 0; } + public final StructBuilder initStruct(StructSize size) { + return WireHelpers.initStructPointer(this.pointer, this.segment, size); + } + public final ListBuilder initStructList(int elementCount, StructSize elementSize) { return WireHelpers.initStructListPointer(this.pointer, this.segment, elementCount, elementSize); } diff --git a/runtime/src/main/java/org/capnproto/ReaderArena.java b/runtime/src/main/java/org/capnproto/ReaderArena.java new file mode 100644 index 0000000..a90d740 --- /dev/null +++ b/runtime/src/main/java/org/capnproto/ReaderArena.java @@ -0,0 +1,7 @@ +package org.capnproto; + +public final class ReaderArena implements Arena { + public SegmentReader tryGetSegment(int id) { + throw new Error("unimplemented"); + } +} diff --git a/runtime/src/main/java/org/capnproto/SegmentBuilder.java b/runtime/src/main/java/org/capnproto/SegmentBuilder.java index 5641099..3d19d6d 100644 --- a/runtime/src/main/java/org/capnproto/SegmentBuilder.java +++ b/runtime/src/main/java/org/capnproto/SegmentBuilder.java @@ -22,6 +22,9 @@ public final class SegmentBuilder extends SegmentReader { return this.pos; } + /** + Allocate `amount` words. + */ public final int allocate(int amount) { if (amount > this.capacity() - this.currentSize()) { return FAILED_ALLOCATION; // no space left; diff --git a/runtime/src/main/java/org/capnproto/WireHelpers.java b/runtime/src/main/java/org/capnproto/WireHelpers.java index 1d0d8cc..93c133d 100644 --- a/runtime/src/main/java/org/capnproto/WireHelpers.java +++ b/runtime/src/main/java/org/capnproto/WireHelpers.java @@ -25,6 +25,15 @@ final class WireHelpers { } } + public static StructBuilder initStructPointer(int refOffset, + SegmentBuilder segment, + StructSize size) { + int ptrOffset = allocate(refOffset, segment, size.total(), WirePointer.STRUCT); + StructPointer.setFromStructSize(segment.buffer, refOffset, size); + return new StructBuilder(segment, ptrOffset * 8, ptrOffset + size.data, + size.data * 64, size.pointers, (byte)0); + } + public static ListBuilder initListPointer(int refOffset, SegmentBuilder segment, int elementCount, @@ -56,7 +65,7 @@ final class WireHelpers { ptrOffset += 1; - return new ListBuilder(segment, ptrOffset, elementCount, wordsPerElement * 64, + return new ListBuilder(segment, ptrOffset * 8, elementCount, wordsPerElement * 64, elementSize.data * 64, elementSize.pointers); }