diff --git a/runtime/src/main/java/org/capnproto/CallContextHook.java b/runtime/src/main/java/org/capnproto/CallContextHook.java new file mode 100644 index 0000000..c5aa043 --- /dev/null +++ b/runtime/src/main/java/org/capnproto/CallContextHook.java @@ -0,0 +1,19 @@ +package org.capnproto; + +import java.util.concurrent.CompletableFuture; + +public interface CallContextHook { + AnyPointer.Reader getParams(); + + void releaseParams(); + + AnyPointer.Builder getResults(); + + CompletableFuture tailCall(RequestHook request); + + void allowCancellation(); + + CompletableFuture onTailCall(); + + ClientHook.VoidPromiseAndPipeline directTailCall(RequestHook request); +} diff --git a/runtime/src/main/java/org/capnproto/ClientHook.java b/runtime/src/main/java/org/capnproto/ClientHook.java index bda1eaf..8e8ad8d 100644 --- a/runtime/src/main/java/org/capnproto/ClientHook.java +++ b/runtime/src/main/java/org/capnproto/ClientHook.java @@ -1,18 +1,35 @@ package org.capnproto; +import java.util.concurrent.CompletableFuture; + public interface ClientHook { Object NULL_CAPABILITY_BRAND = new Object(); Object BROKEN_CAPABILITY_BRAND = new Object(); + Request newCall(long interfaceId, short methodId); + + VoidPromiseAndPipeline call(long interfaceId, short methodId, CallContextHook context); + default ClientHook getResolved() { return null; } + default CompletableFuture whenMoreResolved() { + return null; + } + default Object getBrand() { return NULL_CAPABILITY_BRAND; } + default CompletableFuture whenResolved() { + var promise = whenMoreResolved(); + return promise != null + ? promise.thenCompose(ClientHook::whenResolved) + : CompletableFuture.completedFuture(null); + } + default boolean isNull() { return getBrand() == NULL_CAPABILITY_BRAND; } @@ -25,6 +42,16 @@ public interface ClientHook { return null; } + final class VoidPromiseAndPipeline { + public final CompletableFuture promise; + public final PipelineHook pipeline; + + VoidPromiseAndPipeline(CompletableFuture promise, PipelineHook pipeline) { + this.promise = promise; + this.pipeline = pipeline; + } + } + static ClientHook newBrokenCap(String reason) { return newBrokenClient(reason, false, BROKEN_CAPABILITY_BRAND); } @@ -43,6 +70,25 @@ public interface ClientHook { static private ClientHook newBrokenClient(Throwable exc, boolean resolved, Object brand) { return new ClientHook() { + @Override + public Request newCall(long interfaceId, short methodId) { + return Request.newBrokenRequest(exc); + } + + @Override + public VoidPromiseAndPipeline call(long interfaceId, short methodId, CallContextHook context) { + return new VoidPromiseAndPipeline(CompletableFuture.failedFuture(exc), null); + } + + @Override + public CompletableFuture whenMoreResolved() { + if (resolved) { + return null; + } else { + return CompletableFuture.failedFuture(exc); + } + } + @Override public Object getBrand() { return brand; diff --git a/runtime/src/main/java/org/capnproto/PipelineHook.java b/runtime/src/main/java/org/capnproto/PipelineHook.java new file mode 100644 index 0000000..d242f2d --- /dev/null +++ b/runtime/src/main/java/org/capnproto/PipelineHook.java @@ -0,0 +1,10 @@ +package org.capnproto; + +interface PipelineHook { + + ClientHook getPipelinedCap(PipelineOp[] ops); + + static PipelineHook newBrokenPipeline(Throwable exc) { + return ops -> ClientHook.newBrokenCap(exc); + } +} diff --git a/runtime/src/main/java/org/capnproto/PipelineOp.java b/runtime/src/main/java/org/capnproto/PipelineOp.java new file mode 100644 index 0000000..5232d30 --- /dev/null +++ b/runtime/src/main/java/org/capnproto/PipelineOp.java @@ -0,0 +1,25 @@ +package org.capnproto; + +final class PipelineOp { + + enum Type { + NOOP, + GET_POINTER_FIELD + } + + final PipelineOp.Type type; + final short pointerIndex; + + private PipelineOp(PipelineOp.Type type, short pointerIndex) { + this.type = type; + this.pointerIndex = pointerIndex; + } + + static PipelineOp Noop() { + return new PipelineOp(Type.NOOP, (short) 0); + } + + static PipelineOp PointerField(short pointerIndex) { + return new PipelineOp(Type.GET_POINTER_FIELD, pointerIndex); + } +} diff --git a/runtime/src/main/java/org/capnproto/RemotePromise.java b/runtime/src/main/java/org/capnproto/RemotePromise.java new file mode 100644 index 0000000..9664942 --- /dev/null +++ b/runtime/src/main/java/org/capnproto/RemotePromise.java @@ -0,0 +1,22 @@ +package org.capnproto; + +import java.util.concurrent.CompletableFuture; + +class RemotePromise { + + final CompletableFuture response; + final PipelineHook pipeline; + + RemotePromise(CompletableFuture response, PipelineHook pipeline) { + this.response = response; + this.pipeline = pipeline; + } + + public CompletableFuture getResponse() { + return response; + } + + public PipelineHook getHook() { + return pipeline; + } +} diff --git a/runtime/src/main/java/org/capnproto/Request.java b/runtime/src/main/java/org/capnproto/Request.java new file mode 100644 index 0000000..bedc248 --- /dev/null +++ b/runtime/src/main/java/org/capnproto/Request.java @@ -0,0 +1,42 @@ +package org.capnproto; + +import java.util.concurrent.CompletableFuture; + +public class Request { + + private final AnyPointer.Builder params; + private final RequestHook hook; + + Request(AnyPointer.Builder params, RequestHook hook) { + this.params = params; + this.hook = hook; + } + + AnyPointer.Builder params() { + return params; + } + + CompletableFuture send() { + return null; + } + + static Request newBrokenRequest(Throwable exc) { + final MessageBuilder message = new MessageBuilder(); + + var hook = new RequestHook() { + @Override + public RemotePromise send() { + return new RemotePromise<>(CompletableFuture.failedFuture(exc), null); + } + + @Override + public Object getBrand() { + return null; + } + }; + + var root = message.getRoot(AnyPointer.factory); + return new Request(root, hook); + } +} + diff --git a/runtime/src/main/java/org/capnproto/RequestHook.java b/runtime/src/main/java/org/capnproto/RequestHook.java new file mode 100644 index 0000000..290aece --- /dev/null +++ b/runtime/src/main/java/org/capnproto/RequestHook.java @@ -0,0 +1,6 @@ +package org.capnproto; + +interface RequestHook { + RemotePromise send(); + Object getBrand(); +} diff --git a/runtime/src/main/java/org/capnproto/Response.java b/runtime/src/main/java/org/capnproto/Response.java new file mode 100644 index 0000000..8c188da --- /dev/null +++ b/runtime/src/main/java/org/capnproto/Response.java @@ -0,0 +1,16 @@ +package org.capnproto; + +class Response { + + final ResponseHook hook; + final AnyPointer.Reader results; + + public Response(AnyPointer.Reader reader, ResponseHook hook) { + this.hook = hook; + this.results = reader; + } + + public final T getAs(FromPointerReader factory) { + return this.results.getAs(factory); + } +} \ No newline at end of file diff --git a/runtime/src/main/java/org/capnproto/ResponseHook.java b/runtime/src/main/java/org/capnproto/ResponseHook.java new file mode 100644 index 0000000..7111d11 --- /dev/null +++ b/runtime/src/main/java/org/capnproto/ResponseHook.java @@ -0,0 +1,4 @@ +package org.capnproto; + +interface ResponseHook { +}