// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIB_FIDL_CPP_INTERFACE_HANDLE_H_
#define LIB_FIDL_CPP_INTERFACE_HANDLE_H_

#include <lib/stdcompat/optional.h>
#include <lib/zx/channel.h>
#include <zircon/assert.h>

#include <cstddef>
#include <utility>

#include "lib/fidl/cpp/clone.h"
#include "lib/fidl/cpp/coding_traits.h"
#include "lib/fidl/cpp/interface_request.h"

namespace fidl {
class Builder;
template <typename Interface>
class InterfacePtr;
template <typename Interface>
class SynchronousInterfacePtr;

// The client endpoint of a FIDL channel.
//
// The remote end of the channel expects this end of the channel to speak the
// protocol associated with |Interface|. This type is the dual of
// |InterfaceRequest|.
//
// Unlike an |InterfacePtr|, an |InterfaceHandle| does not have thread affinity
// and can therefore be transferred to another thread or another process. To
// create an |InterfacePtr| to send messages on this channel, call the |Bind()|
// method, either on the |InterfaceHandle| or the |InterfacePtr| object.
//
// See also:
//
//  * |InterfaceRequest|, which is the server analog of an |InterfaceHandle|.
template <typename Interface>
class InterfaceHandle final {
 public:
  // Creates an |InterfaceHandle| whose underlying channel is invalid.
  InterfaceHandle() = default;

  // Creates an |InterfaceHandle| that wraps the given |channel|.
  explicit InterfaceHandle(zx::channel channel) : channel_(std::move(channel)) {}

  InterfaceHandle(const InterfaceHandle& other) = delete;
  InterfaceHandle& operator=(const InterfaceHandle& other) = delete;

  InterfaceHandle(InterfaceHandle&& other) : channel_(std::move(other.channel_)) {}

  InterfaceHandle& operator=(InterfaceHandle&& other) {
    channel_ = std::move(other.channel_);
    return *this;
  }

  // Implicit conversion from nullptr to an |InterfaceHandle| without a valid
  // |channel|.
  InterfaceHandle(std::nullptr_t) {}

  // Implicit conversion from |InterfacePtr| unbinds the channel from the
  // |InterfacePtr|.
  //
  // This requires the caller to provide an rvalue reference, as the caller's
  // InterfacePtr is effectively moved out of.
  //
  // Making this constructor templated ensures that it is not type-instantiated
  // unless it is used, making the InterfacePtr<->InterfaceHandle codependency
  // less fragile.
  //
  // The std::enable_if_t avoids creation of unintended implicit type
  // conversions (especially from anything else that has an "Unbind()"),
  // presumably due to InterfacePtrType being inferred to be something other
  // than InterfacePtr<Interface>.  However, if a caller is trying to use a type
  // that's only incorrect due to not being an rvalue reference, we do permit
  // this constructor to be selected, but then static_assert() with a message
  // suggesting std::move().
  template <typename InterfacePtrType = InterfacePtr<Interface>,
            typename std::enable_if_t<
                std::is_same<InterfacePtr<Interface>,
                             typename std::remove_reference<InterfacePtrType>::type>::value ||
                    std::is_same<SynchronousInterfacePtr<Interface>,
                                 typename std::remove_reference<InterfacePtrType>::type>::value,
                int>
                zero_not_used = 0>
  InterfaceHandle(InterfacePtrType&& ptr) {
    static_assert(std::is_same<InterfacePtr<Interface>&&, decltype(ptr)>::value ||
                      std::is_same<SynchronousInterfacePtr<Interface>&&, decltype(ptr)>::value,
                  "Implicit conversion from InterfacePtr<> (or "
                  "SynchronousInterfacePtr<>) to InterfaceHandle<> requires an rvalue "
                  "reference. Maybe there's a missing std::move(), or consider "
                  "using/providing an InterfaceHandle<> directly instead (particularly "
                  "if the usage prior to this conversion doesn't need to send or receive "
                  "messages).");
    *this = ptr.Unbind();
  }

  // Creates a new channel, retains one endpoint in this |InterfaceHandle| and
  // returns the other as an |InterfaceRequest|.
  //
  // Typically, the returned |InterfaceRequest| is passed to another process,
  // which will implement the server endpoint for the |Interface| protocol.
  //
  // If |NewRequest| fails to create the underlying channel, the returned
  // |InterfaceRequest| will return false from |is_valid()|.
  InterfaceRequest<Interface> NewRequest() {
    zx::channel h1, h2;
    if (zx::channel::create(0, &h1, &h2) != ZX_OK)
      return nullptr;
    channel_ = std::move(h1);
    return InterfaceRequest<Interface>(std::move(h2));
  }

  // Creates an |InterfacePtr| bound to the channel in this |InterfaceHandle|.
  //
  // This function transfers ownership of the underlying channel to the
  // returned |InterfacePtr|, which means the |is_valid()| method will return
  // false after this method returns.
  //
  // Requires the current thread to have a default async_dispatcher_t (e.g., a
  // message loop) in order to read messages from the channel and to monitor the
  // channel for |ZX_CHANNEL_PEER_CLOSED|.
  //
  // Making this method templated ensures that it is not type-instantiated
  // unless it is used, making the InterfacePtr<->InterfaceHandle codependency
  // less fragile.
  template <typename InterfacePtr = InterfacePtr<Interface>>
  inline InterfacePtr Bind() {
    InterfacePtr ptr;
    ptr.Bind(std::move(channel_));
    return ptr;
  }

  template <typename SyncInterfacePtr = SynchronousInterfacePtr<Interface>>
  inline SyncInterfacePtr BindSync() {
    SyncInterfacePtr ptr;
    ptr.Bind(std::move(channel_));
    return ptr;
  }

  // Whether the underlying channel is valid.
  bool is_valid() const { return !!channel_; }
  explicit operator bool() const { return is_valid(); }

  // Transfers ownership of the underlying channel to the caller.
  zx::channel TakeChannel() { return std::move(channel_); }

  // The underlying channel.
  const zx::channel& channel() const { return channel_; }
  void set_channel(zx::channel channel) { channel_ = std::move(channel); }

  void Encode(Encoder* encoder, size_t offset,
              cpp17::optional<HandleInformation> maybe_handle_info = cpp17::nullopt) {
    ZX_DEBUG_ASSERT(maybe_handle_info);
    encoder->EncodeHandle(&channel_, maybe_handle_info->object_type, maybe_handle_info->rights,
                          offset);
  }

  static void Decode(Decoder* decoder, InterfaceHandle<Interface>* value, size_t offset) {
    decoder->DecodeHandle(&value->channel_, offset);
  }

 private:
  zx::channel channel_;
};

// Equality.
template <typename T>
struct Equality<InterfaceHandle<T>> {
  bool operator()(const InterfaceHandle<T>& lhs, const InterfaceHandle<T>& rhs) const {
    return lhs.channel() == rhs.channel();
  }
};

template <typename T>
struct CodingTraits<InterfaceHandle<T>>
    : public EncodableCodingTraits<InterfaceHandle<T>, sizeof(zx_handle_t)> {};

template <typename T>
inline zx_status_t Clone(const InterfaceHandle<T>& value, InterfaceHandle<T>* result) {
  if (!value) {
    *result = InterfaceHandle<T>();
    return ZX_OK;
  }
  return ZX_ERR_ACCESS_DENIED;
}

}  // namespace fidl

#endif  // LIB_FIDL_CPP_INTERFACE_HANDLE_H_
