// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#pragma once

#if CAPNP_LITE
#error "RPC APIs, including this header, are not available in lite mode."
#endif

#include <kj/async.h>
#include <kj/vector.h>
#include "raw-schema.h"
#include "any.h"
#include "pointer-helpers.h"

CAPNP_BEGIN_HEADER

namespace capnp {

template <typename Results>
class Response;

template <typename T>
class RemotePromise: public kj::Promise<Response<T>>, public T::Pipeline {
  // A Promise which supports pipelined calls.  T is typically a struct type.  T must declare
  // an inner "mix-in" type "Pipeline" which implements pipelining; RemotePromise simply
  // multiply-inherits that type along with Promise<Response<T>>.  T::Pipeline must be movable,
  // but does not need to be copyable (i.e. just like Promise<T>).
  //
  // The promise is for an owned pointer so that the RPC system can allocate the MessageReader
  // itself.

public:
  inline RemotePromise(kj::Promise<Response<T>>&& promise, typename T::Pipeline&& pipeline)
      : kj::Promise<Response<T>>(kj::mv(promise)),
        T::Pipeline(kj::mv(pipeline)) {}
  inline RemotePromise(decltype(nullptr))
      : kj::Promise<Response<T>>(nullptr),
        T::Pipeline(nullptr) {}
  KJ_DISALLOW_COPY(RemotePromise);
  RemotePromise(RemotePromise&& other) = default;
  RemotePromise& operator=(RemotePromise&& other) = default;

  kj::Promise<Response<T>> dropPipeline() {
    // Convenience method to convert this into a plain promise.
    return kj::mv(*this);
  }

  static RemotePromise<T> reducePromise(kj::Promise<RemotePromise>&& promise);
  // Hook for KJ so that Promise<RemotePromise<T>> automatically reduces to RemotePromise<T>.
};

class LocalClient;
namespace _ { // private
extern const RawSchema NULL_INTERFACE_SCHEMA;  // defined in schema.c++
class CapabilityServerSetBase;
struct PipelineBuilderPair;
}  // namespace _ (private)

struct Capability {
  // A capability without type-safe methods.  Typed capability clients wrap `Client` and typed
  // capability servers subclass `Server` to dispatch to the regular, typed methods.

  class Client;
  class Server;

  struct _capnpPrivate {
    struct IsInterface;
    static constexpr uint64_t typeId = 0x3;
    static constexpr Kind kind = Kind::INTERFACE;
    static constexpr _::RawSchema const* schema = &_::NULL_INTERFACE_SCHEMA;

    static const _::RawBrandedSchema* brand() {
      return &_::NULL_INTERFACE_SCHEMA.defaultBrand;
    }
  };
};

// =======================================================================================
// Capability clients

class RequestHook;
class ResponseHook;
class PipelineHook;
class ClientHook;

template <typename Params, typename Results>
class Request: public Params::Builder {
  // A call that hasn't been sent yet.  This class extends a Builder for the call's "Params"
  // structure with a method send() that actually sends it.
  //
  // Given a Cap'n Proto method `foo(a :A, b :B): C`, the generated client interface will have
  // a method `Request<FooParams, C> fooRequest()` (as well as a convenience method
  // `RemotePromise<C> foo(A::Reader a, B::Reader b)`).

public:
  inline Request(typename Params::Builder builder, kj::Own<RequestHook>&& hook)
      : Params::Builder(builder), hook(kj::mv(hook)) {}
  inline Request(decltype(nullptr)): Params::Builder(nullptr) {}

  RemotePromise<Results> send() KJ_WARN_UNUSED_RESULT;
  // Send the call and return a promise for the results.

private:
  kj::Own<RequestHook> hook;

  friend class Capability::Client;
  friend struct DynamicCapability;
  template <typename, typename>
  friend class CallContext;
  friend class RequestHook;
};

template <typename Params>
class StreamingRequest: public Params::Builder {
  // Like `Request` but for streaming requests.

public:
  inline StreamingRequest(typename Params::Builder builder, kj::Own<RequestHook>&& hook)
      : Params::Builder(builder), hook(kj::mv(hook)) {}
  inline StreamingRequest(decltype(nullptr)): Params::Builder(nullptr) {}

  kj::Promise<void> send() KJ_WARN_UNUSED_RESULT;

private:
  kj::Own<RequestHook> hook;

  friend class Capability::Client;
  friend struct DynamicCapability;
  template <typename, typename>
  friend class CallContext;
  friend class RequestHook;
};

template <typename Results>
class Response: public Results::Reader {
  // A completed call.  This class extends a Reader for the call's answer structure.  The Response
  // is move-only -- once it goes out-of-scope, the underlying message will be freed.

public:
  inline Response(typename Results::Reader reader, kj::Own<ResponseHook>&& hook)
      : Results::Reader(reader), hook(kj::mv(hook)) {}

private:
  kj::Own<ResponseHook> hook;

  template <typename, typename>
  friend class Request;
  friend class ResponseHook;
};

class Capability::Client {
  // Base type for capability clients.

public:
  typedef Capability Reads;
  typedef Capability Calls;

  Client(decltype(nullptr));
  // If you need to declare a Client before you have anything to assign to it (perhaps because
  // the assignment is going to occur in an if/else scope), you can start by initializing it to
  // `nullptr`.  The resulting client is not meant to be called and throws exceptions from all
  // methods.

  template <typename T, typename = kj::EnableIf<kj::canConvert<T*, Capability::Server*>()>>
  Client(kj::Own<T>&& server);
  // Make a client capability that wraps the given server capability.  The server's methods will
  // only be executed in the given EventLoop, regardless of what thread calls the client's methods.

  template <typename T, typename = kj::EnableIf<kj::canConvert<T*, Client*>()>>
  Client(kj::Promise<T>&& promise);
  // Make a client from a promise for a future client.  The resulting client queues calls until the
  // promise resolves.

  Client(kj::Exception&& exception);
  // Make a broken client that throws the given exception from all calls.

  Client(Client& other);
  Client& operator=(Client& other);
  // Copies by reference counting.  Warning:  This refcounting is not thread-safe.  All copies of
  // the client must remain in one thread.

  Client(Client&&) = default;
  Client& operator=(Client&&) = default;
  // Move constructor avoids reference counting.

  explicit Client(kj::Own<ClientHook>&& hook);
  // For use by the RPC implementation:  Wrap a ClientHook.

  template <typename T>
  typename T::Client castAs();
  // Reinterpret the capability as implementing the given interface.  Note that no error will occur
  // here if the capability does not actually implement this interface, but later method calls will
  // fail.  It's up to the application to decide how indicate that additional interfaces are
  // supported.
  //
  // TODO(perf):  GCC 4.8 / Clang 3.3:  rvalue-qualified version for better performance.

  template <typename T>
  typename T::Client castAs(InterfaceSchema schema);
  // Dynamic version.  `T` must be `DynamicCapability`, and you must `#include <capnp/dynamic.h>`.

  kj::Promise<void> whenResolved();
  // If the capability is actually only a promise, the returned promise resolves once the
  // capability itself has resolved to its final destination (or propagates the exception if
  // the capability promise is rejected).  This is mainly useful for error-checking in the case
  // where no calls are being made.  There is no reason to wait for this before making calls; if
  // the capability does not resolve, the call results will propagate the error.

  Request<AnyPointer, AnyPointer> typelessRequest(
      uint64_t interfaceId, uint16_t methodId,
      kj::Maybe<MessageSize> sizeHint);
  // Make a request without knowing the types of the params or results. You specify the type ID
  // and method number manually.

  kj::Promise<kj::Maybe<int>> getFd();
  // If the capability's server implemented Capability::Server::getFd() returning non-null, and all
  // RPC links between the client and server support FD passing, returns a file descriptor pointing
  // to the same underlying file description as the server did. Returns null if the server provided
  // no FD or if FD passing was unavailable at some intervening link.
  //
  // This returns a Promise to handle the case of an unresolved promise capability, e.g. a
  // pipelined capability. The promise resolves no later than when the capability settles, i.e.
  // the same time `whenResolved()` would complete.
  //
  // The file descriptor will remain open at least as long as the Capability::Client remains alive.
  // If you need it to last longer, you will need to `dup()` it.

  // TODO(someday):  method(s) for Join

protected:
  Client() = default;

  template <typename Params, typename Results>
  Request<Params, Results> newCall(uint64_t interfaceId, uint16_t methodId,
                                   kj::Maybe<MessageSize> sizeHint);
  template <typename Params>
  StreamingRequest<Params> newStreamingCall(uint64_t interfaceId, uint16_t methodId,
                                            kj::Maybe<MessageSize> sizeHint);

private:
  kj::Own<ClientHook> hook;

  static kj::Own<ClientHook> makeLocalClient(kj::Own<Capability::Server>&& server);

  template <typename, Kind>
  friend struct _::PointerHelpers;
  friend struct DynamicCapability;
  friend class Orphanage;
  friend struct DynamicStruct;
  friend struct DynamicList;
  template <typename, Kind>
  friend struct List;
  friend class _::CapabilityServerSetBase;
  friend class ClientHook;
};

// =======================================================================================
// Capability servers

class CallContextHook;

template <typename Params, typename Results>
class CallContext: public kj::DisallowConstCopy {
  // Wrapper around CallContextHook with a specific return type.
  //
  // Methods of this class may only be called from within the server's event loop, not from other
  // threads.
  //
  // The CallContext becomes invalid as soon as the call reports completion.

public:
  explicit CallContext(CallContextHook& hook);

  typename Params::Reader getParams();
  // Get the params payload.

  void releaseParams();
  // Release the params payload.  getParams() will throw an exception after this is called.
  // Releasing the params may allow the RPC system to free up buffer space to handle other
  // requests.  Long-running asynchronous methods should try to call this as early as is
  // convenient.

  typename Results::Builder getResults(kj::Maybe<MessageSize> sizeHint = nullptr);
  typename Results::Builder initResults(kj::Maybe<MessageSize> sizeHint = nullptr);
  void setResults(typename Results::Reader value);
  void adoptResults(Orphan<Results>&& value);
  Orphanage getResultsOrphanage(kj::Maybe<MessageSize> sizeHint = nullptr);
  // Manipulate the results payload.  The "Return" message (part of the RPC protocol) will
  // typically be allocated the first time one of these is called.  Some RPC systems may
  // allocate these messages in a limited space (such as a shared memory segment), therefore the
  // application should delay calling these as long as is convenient to do so (but don't delay
  // if doing so would require extra copies later).
  //
  // `sizeHint` indicates a guess at the message size.  This will usually be used to decide how
  // much space to allocate for the first message segment (don't worry: only space that is actually
  // used will be sent on the wire).  If omitted, the system decides.  The message root pointer
  // should not be included in the size.  So, if you are simply going to copy some existing message
  // directly into the results, just call `.totalSize()` and pass that in.

  void setPipeline(typename Results::Pipeline&& pipeline);
  void setPipeline(typename Results::Pipeline& pipeline);
  // Tells the system where the capabilities in the response will eventually resolve to. This
  // allows requests that are promise-pipelined on this call's results to continue their journey
  // to the final destination before this call itself has completed.
  //
  // This is particularly useful when forwarding RPC calls to other remote servers, but where a
  // tail call can't be used. For example, imagine Alice calls `foo()` on Bob. In `foo()`'s
  // implementation, Bob calls `bar()` on Charlie. `bar()` returns a capability to Bob, and then
  // `foo()` returns the same capability on to Alice. Now imagine Alice is actually using promise
  // pipelining in a chain like `foo().getCap().baz()`. The `baz()` call will travel to Bob as a
  // pipelined call without waiting for `foo()` to return first. But once it gets to Bob, the
  // message has to patiently wait until `foo()` has completed there, before it can then be
  // forwarded on to Charlie. It would be better if immediately upon Bob calling `bar()` on
  // Charlie, then Alice's call to `baz()` could be forwarded to Charlie as a pipelined call,
  // without waiting for `bar()` to return. This would avoid a network round trip of latency
  // between Bob and Charlie.
  //
  // To solve this problem, Bob takes the pipeline object from the `bar()` call, transforms it into
  // an appropriate pipeline for a `foo()` call, and passes that to `setPipeline()`. This allows
  // Alice's pipelined `baz()` call to flow through immediately. The code looks like:
  //
  //     kj::Promise<void> foo(FooContext context) {
  //       auto barPromise = charlie.barRequest().send();
  //
  //       // Set up the final pipeline using pipelined capabilities from `barPromise`.
  //       capnp::PipelineBuilder<FooResults> pipeline;
  //       pipeline.setResultCap(barPromise.getSomeCap());
  //       context.setPipeline(pipeline.build());
  //
  //       // Now actually wait for the results and process them.
  //       return barPromise
  //           .then([context](capnp::Response<BarResults> response) mutable {
  //         auto results = context.initResults();
  //
  //         // Make sure to set up the capabilities exactly as we did in the pipeline.
  //         results.setResultCap(response.getSomeCap());
  //
  //         // ... do other stuff with the real response ...
  //       });
  //     }
  //
  // Of course, if `foo()` and `bar()` return exactly the same type, and Bob doesn't intend
  // to do anything with `bar()`'s response except pass it through, then `tailCall()` is a better
  // choice here. `setPipeline()` is useful when some transformation is needed on the response,
  // or the middleman needs to inspect the response for some reason.
  //
  // Note: This method has an overload that takes an lvalue reference for convenience. This
  //   overload increments the refcount on the underlying PipelineHook -- it does not keep the
  //   reference.

  template <typename SubParams>
  kj::Promise<void> tailCall(Request<SubParams, Results>&& tailRequest);
  // Resolve the call by making a tail call.  `tailRequest` is a request that has been filled in
  // but not yet sent.  The context will send the call, then fill in the results with the result
  // of the call.  If tailCall() is used, {get,init,set,adopt}Results (above) *must not* be called.
  //
  // The RPC implementation may be able to optimize a tail call to another machine such that the
  // results never actually pass through this machine.  Even if no such optimization is possible,
  // `tailCall()` may allow pipelined calls to be forwarded optimistically to the new call site.
  //
  // In general, this should be the last thing a method implementation calls, and the promise
  // returned from `tailCall()` should then be returned by the method implementation.

  void allowCancellation();
  // Indicate that it is OK for the RPC system to discard its Promise for this call's result if
  // the caller cancels the call, thereby transitively canceling any asynchronous operations the
  // call implementation was performing.  This is not done by default because it could represent a
  // security risk:  applications must be carefully written to ensure that they do not end up in
  // a bad state if an operation is canceled at an arbitrary point.  However, for long-running
  // method calls that hold significant resources, prompt cancellation is often useful.
  //
  // Keep in mind that asynchronous cancellation cannot occur while the method is synchronously
  // executing on a local thread.  The method must perform an asynchronous operation or call
  // `EventLoop::current().evalLater()` to yield control.
  //
  // Note:  You might think that we should offer `onCancel()` and/or `isCanceled()` methods that
  // provide notification when the caller cancels the request without forcefully killing off the
  // promise chain.  Unfortunately, this composes poorly with promise forking:  the canceled
  // path may be just one branch of a fork of the result promise.  The other branches still want
  // the call to continue.  Promise forking is used within the Cap'n Proto implementation -- in
  // particular each pipelined call forks the result promise.  So, if a caller made a pipelined
  // call and then dropped the original object, the call should not be canceled, but it would be
  // excessively complicated for the framework to avoid notififying of cancellation as long as
  // pipelined calls still exist.

private:
  CallContextHook* hook;

  friend class Capability::Server;
  friend struct DynamicCapability;
  friend class CallContextHook;
};

template <typename Params>
class StreamingCallContext: public kj::DisallowConstCopy {
  // Like CallContext but for streaming calls.

public:
  explicit StreamingCallContext(CallContextHook& hook);

  typename Params::Reader getParams();
  void releaseParams();

  // Note: tailCall() is not supported because:
  // - It would significantly complicate the implementation of streaming.
  // - It wouldn't be particularly useful since streaming calls don't return anything, and they
  //   already compensate for latency.

  void allowCancellation();

private:
  CallContextHook* hook;

  friend class Capability::Server;
  friend struct DynamicCapability;
  friend class CallContextHook;
};

class Capability::Server {
  // Objects implementing a Cap'n Proto interface must subclass this.  Typically, such objects
  // will instead subclass a typed Server interface which will take care of implementing
  // dispatchCall().

public:
  typedef Capability Serves;

  struct DispatchCallResult {
    kj::Promise<void> promise;
    // Promise for completion of the call.

    bool isStreaming;
    // If true, this method was declared as `-> stream;`. No other calls should be permitted until
    // this call finishes, and if this call throws an exception, all future calls will throw the
    // same exception.
  };

  virtual DispatchCallResult dispatchCall(uint64_t interfaceId, uint16_t methodId,
                                          CallContext<AnyPointer, AnyPointer> context) = 0;
  // Call the given method.  `params` is the input struct, and should be released as soon as it
  // is no longer needed.  `context` may be used to allocate the output struct and deal with
  // cancellation.

  virtual kj::Maybe<int> getFd() { return nullptr; }
  // If this capability is backed by a file descriptor that is safe to directly expose to clients,
  // returns that FD. When FD passing has been enabled in the RPC layer, this FD may be sent to
  // other processes along with the capability.

  virtual kj::Maybe<kj::Promise<Capability::Client>> shortenPath();
  // If this returns non-null, then it is a promise which, when resolved, points to a new
  // capability to which future calls can be sent. Use this in cases where an object implementation
  // might discover a more-optimized path some time after it starts.
  //
  // Implementing this (and returning non-null) will cause the capability to be advertised as a
  // promise at the RPC protocol level. Once the promise returned by shortenPath() resolves, the
  // remote client will receive a `Resolve` message updating it to point at the new destination.
  //
  // `shortenPath()` can also be used as a hack to shut up the client. If shortenPath() returns
  // a promise that resolves to an exception, then the client will be notified that the capability
  // is now broken. Assuming the client is using a correct RPC implemnetation, this should cause
  // all further calls initiated by the client to this capability to immediately fail client-side,
  // sparing the server's bandwidth.
  //
  // The default implementation always returns nullptr.

  // TODO(someday):  Method which can optionally be overridden to implement Join when the object is
  //   a proxy.

protected:
  inline Capability::Client thisCap();
  // Get a capability pointing to this object, much like the `this` keyword.
  //
  // The effect of this method is undefined if:
  // - No capability client has been created pointing to this object. (This is always the case in
  //   the server's constructor.)
  // - The capability client pointing at this object has been destroyed. (This is always the case
  //   in the server's destructor.)
  // - Multiple capability clients have been created around the same server (possible if the server
  //   is refcounted, which is not recommended since the client itself provides refcounting).

  template <typename Params, typename Results>
  CallContext<Params, Results> internalGetTypedContext(
      CallContext<AnyPointer, AnyPointer> typeless);
  template <typename Params>
  StreamingCallContext<Params> internalGetTypedStreamingContext(
      CallContext<AnyPointer, AnyPointer> typeless);
  DispatchCallResult internalUnimplemented(const char* actualInterfaceName,
                                           uint64_t requestedTypeId);
  DispatchCallResult internalUnimplemented(const char* interfaceName,
                                           uint64_t typeId, uint16_t methodId);
  kj::Promise<void> internalUnimplemented(const char* interfaceName, const char* methodName,
                                          uint64_t typeId, uint16_t methodId);

private:
  ClientHook* thisHook = nullptr;
  friend class LocalClient;
};

// =======================================================================================

template <typename T>
class PipelineBuilder: public T::Builder {
  // Convenience class to build a Pipeline object for use with CallContext::setPipeline().
  //
  // Building a pipeline object is like building an RPC result message, except that you only need
  // to fill in the capabilities, since the purpose is only to allow pipelined RPC requests to
  // flow through.
  //
  // See the docs for `CallContext::setPipeline()` for an example.

public:
  PipelineBuilder(uint firstSegmentWords = 64);
  // Construct a builder, allocating the given number of words for the first segment of the backing
  // message. Since `PipelineBuilder` is typically used with small RPC messages, the default size
  // here is considerably smaller than with MallocMessageBuilder.

  typename T::Pipeline build();
  // Constructs a `Pipeline` object backed by the current content of this builder. Calling this
  // consumes the `PipelineBuilder`; no further methods can be invoked.

private:
  kj::Own<PipelineHook> hook;

  PipelineBuilder(_::PipelineBuilderPair pair);
};

// =======================================================================================

class ReaderCapabilityTable: private _::CapTableReader {
  // Class which imbues Readers with the ability to read capabilities.
  //
  // In Cap'n Proto format, the encoding of a capability pointer is simply an integer index into
  // an external table. Since these pointers fundamentally point outside the message, a
  // MessageReader by default has no idea what they point at, and therefore reading capabilities
  // from such a reader will throw exceptions.
  //
  // In order to be able to read capabilities, you must first attach a capability table, using
  // this class. By "imbuing" a Reader, you get a new Reader which will interpret capability
  // pointers by treating them as indexes into the ReaderCapabilityTable.
  //
  // Note that when using Cap'n Proto's RPC system, this is handled automatically.

public:
  explicit ReaderCapabilityTable(kj::Array<kj::Maybe<kj::Own<ClientHook>>> table);
  KJ_DISALLOW_COPY(ReaderCapabilityTable);

  template <typename T>
  T imbue(T reader);
  // Return a reader equivalent to `reader` except that when reading capability-valued fields,
  // the capabilities are looked up in this table.

private:
  kj::Array<kj::Maybe<kj::Own<ClientHook>>> table;

  kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override;
};

class BuilderCapabilityTable: private _::CapTableBuilder {
  // Class which imbues Builders with the ability to read and write capabilities.
  //
  // This is much like ReaderCapabilityTable, except for builders. The table starts out empty,
  // but capabilities can be added to it over time.

public:
  BuilderCapabilityTable();
  KJ_DISALLOW_COPY(BuilderCapabilityTable);

  inline kj::ArrayPtr<kj::Maybe<kj::Own<ClientHook>>> getTable() { return table; }

  template <typename T>
  T imbue(T builder);
  // Return a builder equivalent to `builder` except that when reading capability-valued fields,
  // the capabilities are looked up in this table.

private:
  kj::Vector<kj::Maybe<kj::Own<ClientHook>>> table;

  kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override;
  uint injectCap(kj::Own<ClientHook>&& cap) override;
  void dropCap(uint index) override;
};

// =======================================================================================

namespace _ {  // private

class CapabilityServerSetBase {
public:
  Capability::Client addInternal(kj::Own<Capability::Server>&& server, void* ptr);
  kj::Promise<void*> getLocalServerInternal(Capability::Client& client);
};

}  // namespace _ (private)

template <typename T>
class CapabilityServerSet: private _::CapabilityServerSetBase {
  // Allows a server to recognize its own capabilities when passed back to it, and obtain the
  // underlying Server objects associated with them.
  //
  // All objects in the set must have the same interface type T. The objects may implement various
  // interfaces derived from T (and in fact T can be `capnp::Capability` to accept all objects),
  // but note that if you compile with RTTI disabled then you will not be able to down-cast through
  // virtual inheritance, and all inheritance between server interfaces is virtual. So, with RTTI
  // disabled, you will likely need to set T to be the most-derived Cap'n Proto interface type,
  // and you server class will need to be directly derived from that, so that you can use
  // static_cast (or kj::downcast) to cast to it after calling getLocalServer(). (If you compile
  // with RTTI, then you can freely dynamic_cast and ignore this issue!)

public:
  CapabilityServerSet() = default;
  KJ_DISALLOW_COPY(CapabilityServerSet);

  typename T::Client add(kj::Own<typename T::Server>&& server);
  // Create a new capability Client for the given Server and also add this server to the set.

  kj::Promise<kj::Maybe<typename T::Server&>> getLocalServer(typename T::Client& client);
  // Given a Client pointing to a server previously passed to add(), return the corresponding
  // Server. This returns a promise because if the input client is itself a promise, this must
  // wait for it to resolve. Keep in mind that the server will be deleted when all clients are
  // gone, so the caller should make sure to keep the client alive (hence why this method only
  // accepts an lvalue input).
};

// =======================================================================================
// Hook interfaces which must be implemented by the RPC system.  Applications never call these
// directly; the RPC system implements them and the types defined earlier in this file wrap them.

class RequestHook {
  // Hook interface implemented by RPC system representing a request being built.

public:
  virtual RemotePromise<AnyPointer> send() = 0;
  // Send the call and return a promise for the result.

  virtual kj::Promise<void> sendStreaming() = 0;
  // Send a streaming call.

  virtual const void* getBrand() = 0;
  // Returns a void* that identifies who made this request.  This can be used by an RPC adapter to
  // discover when tail call is going to be sent over its own connection and therefore can be
  // optimized into a remote tail call.

  template <typename T, typename U>
  inline static kj::Own<RequestHook> from(Request<T, U>&& request) {
    return kj::mv(request.hook);
  }
};

class ResponseHook {
  // Hook interface implemented by RPC system representing a response.
  //
  // At present this class has no methods.  It exists only for garbage collection -- when the
  // ResponseHook is destroyed, the results can be freed.

public:
  virtual ~ResponseHook() noexcept(false);
  // Just here to make sure the type is dynamic.

  template <typename T>
  inline static kj::Own<ResponseHook> from(Response<T>&& response) {
    return kj::mv(response.hook);
  }
};

// class PipelineHook is declared in any.h because it is needed there.

class ClientHook {
public:
  ClientHook();

  virtual Request<AnyPointer, AnyPointer> newCall(
      uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) = 0;
  // Start a new call, allowing the client to allocate request/response objects as it sees fit.
  // This version is used when calls are made from application code in the local process.

  struct VoidPromiseAndPipeline {
    kj::Promise<void> promise;
    kj::Own<PipelineHook> pipeline;
  };

  virtual VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId,
                                      kj::Own<CallContextHook>&& context) = 0;
  // Call the object, but the caller controls allocation of the request/response objects.  If the
  // callee insists on allocating these objects itself, it must make a copy.  This version is used
  // when calls come in over the network via an RPC system.  Note that even if the returned
  // `Promise<void>` is discarded, the call may continue executing if any pipelined calls are
  // waiting for it.
  //
  // Since the caller of this method chooses the CallContext implementation, it is the caller's
  // responsibility to ensure that the returned promise is not canceled unless allowed via
  // the context's `allowCancellation()`.
  //
  // The call must not begin synchronously; the callee must arrange for the call to begin in a
  // later turn of the event loop. Otherwise, application code may call back and affect the
  // callee's state in an unexpected way.

  virtual kj::Maybe<ClientHook&> getResolved() = 0;
  // If this ClientHook is a promise that has already resolved, returns the inner, resolved version
  // of the capability.  The caller may permanently replace this client with the resolved one if
  // desired.  Returns null if the client isn't a promise or hasn't resolved yet -- use
  // `whenMoreResolved()` to distinguish between them.

  virtual kj::Maybe<kj::Promise<kj::Own<ClientHook>>> whenMoreResolved() = 0;
  // If this client is a settled reference (not a promise), return nullptr.  Otherwise, return a
  // promise that eventually resolves to a new client that is closer to being the final, settled
  // client (i.e. the value eventually returned by `getResolved()`).  Calling this repeatedly
  // should eventually produce a settled client.

  kj::Promise<void> whenResolved();
  // Repeatedly calls whenMoreResolved() until it returns nullptr.

  virtual kj::Own<ClientHook> addRef() = 0;
  // Return a new reference to the same capability.

  virtual const void* getBrand() = 0;
  // Returns a void* that identifies who made this client.  This can be used by an RPC adapter to
  // discover when a capability it needs to marshal is one that it created in the first place, and
  // therefore it can transfer the capability without proxying.

  static const uint NULL_CAPABILITY_BRAND;
  static const uint BROKEN_CAPABILITY_BRAND;
  // Values are irrelevant; used for pointers.

  inline bool isNull() { return getBrand() == &NULL_CAPABILITY_BRAND; }
  // Returns true if the capability was created as a result of assigning a Client to null or by
  // reading a null pointer out of a Cap'n Proto message.

  inline bool isError() { return getBrand() == &BROKEN_CAPABILITY_BRAND; }
  // Returns true if the capability was created by newBrokenCap().

  virtual kj::Maybe<int> getFd() = 0;
  // Implements Capability::Client::getFd(). If this returns null but whenMoreResolved() returns
  // non-null, then Capability::Client::getFd() waits for resolution and tries again.

  static kj::Own<ClientHook> from(Capability::Client client) { return kj::mv(client.hook); }
};

class CallContextHook {
  // Hook interface implemented by RPC system to manage a call on the server side.  See
  // CallContext<T>.

public:
  virtual AnyPointer::Reader getParams() = 0;
  virtual void releaseParams() = 0;
  virtual AnyPointer::Builder getResults(kj::Maybe<MessageSize> sizeHint) = 0;
  virtual kj::Promise<void> tailCall(kj::Own<RequestHook>&& request) = 0;
  virtual void allowCancellation() = 0;

  virtual void setPipeline(kj::Own<PipelineHook>&& pipeline) = 0;

  virtual kj::Promise<AnyPointer::Pipeline> onTailCall() = 0;
  // If `tailCall()` is called, resolves to the PipelineHook from the tail call.  An
  // implementation of `ClientHook::call()` is allowed to call this at most once.

  virtual ClientHook::VoidPromiseAndPipeline directTailCall(kj::Own<RequestHook>&& request) = 0;
  // Call this when you would otherwise call onTailCall() immediately followed by tailCall().
  // Implementations of tailCall() should typically call directTailCall() and then fulfill the
  // promise fulfiller for onTailCall() with the returned pipeline.

  virtual kj::Own<CallContextHook> addRef() = 0;

  template <typename Params, typename Results>
  static CallContextHook& from(CallContext<Params, Results>& context) { return *context.hook; }
  template <typename Params>
  static CallContextHook& from(StreamingCallContext<Params>& context) { return *context.hook; }
};

kj::Own<ClientHook> newLocalPromiseClient(kj::Promise<kj::Own<ClientHook>>&& promise);
// Returns a ClientHook that queues up calls until `promise` resolves, then forwards them to
// the new client.  This hook's `getResolved()` and `whenMoreResolved()` methods will reflect the
// redirection to the eventual replacement client.

kj::Own<PipelineHook> newLocalPromisePipeline(kj::Promise<kj::Own<PipelineHook>>&& promise);
// Returns a PipelineHook that queues up calls until `promise` resolves, then forwards them to
// the new pipeline.

kj::Own<ClientHook> newBrokenCap(kj::StringPtr reason);
kj::Own<ClientHook> newBrokenCap(kj::Exception&& reason);
// Helper function that creates a capability which simply throws exceptions when called.

kj::Own<PipelineHook> newBrokenPipeline(kj::Exception&& reason);
// Helper function that creates a pipeline which simply throws exceptions when called.

Request<AnyPointer, AnyPointer> newBrokenRequest(
    kj::Exception&& reason, kj::Maybe<MessageSize> sizeHint);
// Helper function that creates a Request object that simply throws exceptions when sent.

// =======================================================================================
// Extend PointerHelpers for interfaces

namespace _ {  // private

template <typename T>
struct PointerHelpers<T, Kind::INTERFACE> {
  static inline typename T::Client get(PointerReader reader) {
    return typename T::Client(reader.getCapability());
  }
  static inline typename T::Client get(PointerBuilder builder) {
    return typename T::Client(builder.getCapability());
  }
  static inline void set(PointerBuilder builder, typename T::Client&& value) {
    builder.setCapability(kj::mv(value.Capability::Client::hook));
  }
  static inline void set(PointerBuilder builder, typename T::Client& value) {
    builder.setCapability(value.Capability::Client::hook->addRef());
  }
  static inline void adopt(PointerBuilder builder, Orphan<T>&& value) {
    builder.adopt(kj::mv(value.builder));
  }
  static inline Orphan<T> disown(PointerBuilder builder) {
    return Orphan<T>(builder.disown());
  }
};

}  // namespace _ (private)

// =======================================================================================
// Extend List for interfaces

template <typename T>
struct List<T, Kind::INTERFACE> {
  List() = delete;

  class Reader {
  public:
    typedef List<T> Reads;

    Reader() = default;
    inline explicit Reader(_::ListReader reader): reader(reader) {}

    inline uint size() const { return unbound(reader.size() / ELEMENTS); }
    inline typename T::Client operator[](uint index) const {
      KJ_IREQUIRE(index < size());
      return typename T::Client(reader.getPointerElement(
          bounded(index) * ELEMENTS).getCapability());
    }

    typedef _::IndexingIterator<const Reader, typename T::Client> Iterator;
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }

    inline MessageSize totalSize() const {
      return reader.totalSize().asPublic();
    }

  private:
    _::ListReader reader;
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
    template <typename U, Kind K>
    friend struct List;
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
  };

  class Builder {
  public:
    typedef List<T> Builds;

    Builder() = delete;
    inline Builder(decltype(nullptr)) {}
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}

    inline operator Reader() const { return Reader(builder.asReader()); }
    inline Reader asReader() const { return Reader(builder.asReader()); }

    inline uint size() const { return unbound(builder.size() / ELEMENTS); }
    inline typename T::Client operator[](uint index) {
      KJ_IREQUIRE(index < size());
      return typename T::Client(builder.getPointerElement(
          bounded(index) * ELEMENTS).getCapability());
    }
    inline void set(uint index, typename T::Client value) {
      KJ_IREQUIRE(index < size());
      builder.getPointerElement(bounded(index) * ELEMENTS).setCapability(kj::mv(value.hook));
    }
    inline void adopt(uint index, Orphan<T>&& value) {
      KJ_IREQUIRE(index < size());
      builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value));
    }
    inline Orphan<T> disown(uint index) {
      KJ_IREQUIRE(index < size());
      return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown());
    }

    typedef _::IndexingIterator<Builder, typename T::Client> Iterator;
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }

  private:
    _::ListBuilder builder;
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
  };

private:
  inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
    return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS);
  }
  inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
    return builder.getList(ElementSize::POINTER, defaultValue);
  }
  inline static _::ListReader getFromPointer(
      const _::PointerReader& reader, const word* defaultValue) {
    return reader.getList(ElementSize::POINTER, defaultValue);
  }

  template <typename U, Kind k>
  friend struct List;
  template <typename U, Kind K>
  friend struct _::PointerHelpers;
};

// =======================================================================================
// Inline implementation details

template <typename T>
RemotePromise<T> RemotePromise<T>::reducePromise(kj::Promise<RemotePromise>&& promise) {
  kj::Tuple<kj::Promise<Response<T>>, kj::Promise<kj::Own<PipelineHook>>> splitPromise =
      promise.then([](RemotePromise&& inner) {
    // `inner` is multiply-inherited, and we want to move away each superclass separately.
    // Let's create two references to make clear what we're doing (though this is not strictly
    // necessary).
    kj::Promise<Response<T>>& innerPromise = inner;
    typename T::Pipeline& innerPipeline = inner;
    return kj::tuple(kj::mv(innerPromise), PipelineHook::from(kj::mv(innerPipeline)));
  }).split();

  return RemotePromise(kj::mv(kj::get<0>(splitPromise)),
      typename T::Pipeline(AnyPointer::Pipeline(
          newLocalPromisePipeline(kj::mv(kj::get<1>(splitPromise))))));
}

template <typename Params, typename Results>
RemotePromise<Results> Request<Params, Results>::send() {
  auto typelessPromise = hook->send();
  hook = nullptr;  // prevent reuse

  // Convert the Promise to return the correct response type.
  // Explicitly upcast to kj::Promise to make clear that calling .then() doesn't invalidate the
  // Pipeline part of the RemotePromise.
  auto typedPromise = kj::implicitCast<kj::Promise<Response<AnyPointer>>&>(typelessPromise)
      .then([](Response<AnyPointer>&& response) -> Response<Results> {
        return Response<Results>(response.getAs<Results>(), kj::mv(response.hook));
      });

  // Wrap the typeless pipeline in a typed wrapper.
  typename Results::Pipeline typedPipeline(
      kj::mv(kj::implicitCast<AnyPointer::Pipeline&>(typelessPromise)));

  return RemotePromise<Results>(kj::mv(typedPromise), kj::mv(typedPipeline));
}

template <typename Params>
kj::Promise<void> StreamingRequest<Params>::send() {
  auto promise = hook->sendStreaming();
  hook = nullptr;  // prevent reuse
  return promise;
}

inline Capability::Client::Client(kj::Own<ClientHook>&& hook): hook(kj::mv(hook)) {}
template <typename T, typename>
inline Capability::Client::Client(kj::Own<T>&& server)
    : hook(makeLocalClient(kj::mv(server))) {}
template <typename T, typename>
inline Capability::Client::Client(kj::Promise<T>&& promise)
    : hook(newLocalPromiseClient(promise.then([](T&& t) { return kj::mv(t.hook); }))) {}
inline Capability::Client::Client(Client& other): hook(other.hook->addRef()) {}
inline Capability::Client& Capability::Client::operator=(Client& other) {
  hook = other.hook->addRef();
  return *this;
}
template <typename T>
inline typename T::Client Capability::Client::castAs() {
  return typename T::Client(hook->addRef());
}
inline Request<AnyPointer, AnyPointer> Capability::Client::typelessRequest(
    uint64_t interfaceId, uint16_t methodId,
    kj::Maybe<MessageSize> sizeHint) {
  return newCall<AnyPointer, AnyPointer>(interfaceId, methodId, sizeHint);
}
template <typename Params, typename Results>
inline Request<Params, Results> Capability::Client::newCall(
    uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) {
  auto typeless = hook->newCall(interfaceId, methodId, sizeHint);
  return Request<Params, Results>(typeless.template getAs<Params>(), kj::mv(typeless.hook));
}
template <typename Params>
inline StreamingRequest<Params> Capability::Client::newStreamingCall(
    uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) {
  auto typeless = hook->newCall(interfaceId, methodId, sizeHint);
  return StreamingRequest<Params>(typeless.template getAs<Params>(), kj::mv(typeless.hook));
}

template <typename Params, typename Results>
inline CallContext<Params, Results>::CallContext(CallContextHook& hook): hook(&hook) {}
template <typename Params>
inline StreamingCallContext<Params>::StreamingCallContext(CallContextHook& hook): hook(&hook) {}
template <typename Params, typename Results>
inline typename Params::Reader CallContext<Params, Results>::getParams() {
  return hook->getParams().template getAs<Params>();
}
template <typename Params>
inline typename Params::Reader StreamingCallContext<Params>::getParams() {
  return hook->getParams().template getAs<Params>();
}
template <typename Params, typename Results>
inline void CallContext<Params, Results>::releaseParams() {
  hook->releaseParams();
}
template <typename Params>
inline void StreamingCallContext<Params>::releaseParams() {
  hook->releaseParams();
}
template <typename Params, typename Results>
inline typename Results::Builder CallContext<Params, Results>::getResults(
    kj::Maybe<MessageSize> sizeHint) {
  // `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401
  return hook->getResults(sizeHint).template getAs<Results>();
}
template <typename Params, typename Results>
inline typename Results::Builder CallContext<Params, Results>::initResults(
    kj::Maybe<MessageSize> sizeHint) {
  // `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401
  return hook->getResults(sizeHint).template initAs<Results>();
}
template <typename Params, typename Results>
inline void CallContext<Params, Results>::setResults(typename Results::Reader value) {
  hook->getResults(value.totalSize()).template setAs<Results>(value);
}
template <typename Params, typename Results>
inline void CallContext<Params, Results>::adoptResults(Orphan<Results>&& value) {
  hook->getResults(nullptr).adopt(kj::mv(value));
}
template <typename Params, typename Results>
inline Orphanage CallContext<Params, Results>::getResultsOrphanage(
    kj::Maybe<MessageSize> sizeHint) {
  return Orphanage::getForMessageContaining(hook->getResults(sizeHint));
}
template <typename Params, typename Results>
void CallContext<Params, Results>::setPipeline(typename Results::Pipeline&& pipeline) {
  hook->setPipeline(PipelineHook::from(kj::mv(pipeline)));
}
template <typename Params, typename Results>
void CallContext<Params, Results>::setPipeline(typename Results::Pipeline& pipeline) {
  hook->setPipeline(PipelineHook::from(pipeline).addRef());
}
template <typename Params, typename Results>
template <typename SubParams>
inline kj::Promise<void> CallContext<Params, Results>::tailCall(
    Request<SubParams, Results>&& tailRequest) {
  return hook->tailCall(kj::mv(tailRequest.hook));
}
template <typename Params, typename Results>
inline void CallContext<Params, Results>::allowCancellation() {
  hook->allowCancellation();
}
template <typename Params>
inline void StreamingCallContext<Params>::allowCancellation() {
  hook->allowCancellation();
}

template <typename Params, typename Results>
CallContext<Params, Results> Capability::Server::internalGetTypedContext(
    CallContext<AnyPointer, AnyPointer> typeless) {
  return CallContext<Params, Results>(*typeless.hook);
}

template <typename Params>
StreamingCallContext<Params> Capability::Server::internalGetTypedStreamingContext(
    CallContext<AnyPointer, AnyPointer> typeless) {
  return StreamingCallContext<Params>(*typeless.hook);
}

Capability::Client Capability::Server::thisCap() {
  return Client(thisHook->addRef());
}

namespace _ { // private

struct PipelineBuilderPair {
  AnyPointer::Builder root;
  kj::Own<PipelineHook> hook;
};

PipelineBuilderPair newPipelineBuilder(uint firstSegmentWords);

}  // namespace _ (private)

template <typename T>
PipelineBuilder<T>::PipelineBuilder(uint firstSegmentWords)
    : PipelineBuilder(_::newPipelineBuilder(firstSegmentWords)) {}

template <typename T>
PipelineBuilder<T>::PipelineBuilder(_::PipelineBuilderPair pair)
    : T::Builder(pair.root.initAs<T>()),
      hook(kj::mv(pair.hook)) {}

template <typename T>
typename T::Pipeline PipelineBuilder<T>::build() {
  // Prevent subsequent accidental modification. A good compiler should be able to optimize this
  // assignment away assuming the PipelineBuilder is not accessed again after this point.
  static_cast<typename T::Builder&>(*this) = nullptr;

  return typename T::Pipeline(AnyPointer::Pipeline(kj::mv(hook)));
}

template <typename T>
T ReaderCapabilityTable::imbue(T reader) {
  return T(_::PointerHelpers<FromReader<T>>::getInternalReader(reader).imbue(this));
}

template <typename T>
T BuilderCapabilityTable::imbue(T builder) {
  return T(_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::mv(builder)).imbue(this));
}

template <typename T>
typename T::Client CapabilityServerSet<T>::add(kj::Own<typename T::Server>&& server) {
  void* ptr = reinterpret_cast<void*>(server.get());
  // Clang insists that `castAs` is a template-dependent member and therefore we need the
  // `template` keyword here, but AFAICT this is wrong: addImpl() is not a template.
  return addInternal(kj::mv(server), ptr).template castAs<T>();
}

template <typename T>
kj::Promise<kj::Maybe<typename T::Server&>> CapabilityServerSet<T>::getLocalServer(
    typename T::Client& client) {
  return getLocalServerInternal(client)
      .then([](void* server) -> kj::Maybe<typename T::Server&> {
    if (server == nullptr) {
      return nullptr;
    } else {
      return *reinterpret_cast<typename T::Server*>(server);
    }
  });
}

template <typename T>
struct Orphanage::GetInnerReader<T, Kind::INTERFACE> {
  static inline kj::Own<ClientHook> apply(typename T::Client t) {
    return ClientHook::from(kj::mv(t));
  }
};

#define CAPNP_CAPABILITY_H_INCLUDED  // for testing includes in unit test

}  // namespace capnp

CAPNP_END_HEADER
