// 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_UTILS_BIND_H_
#define LIB_FIDL_UTILS_BIND_H_

#include <lib/async/dispatcher.h>
#include <lib/fidl-async/bind.h>
#include <lib/zx/channel.h>
#include <zircon/assert.h>
#include <zircon/fidl.h>

#include <functional>
#include <type_traits>

#include <fbl/macros.h>

namespace fidl {

// A wrapper class which helps binding operations to a channel, and which
// helps creating C-compatible member-binding functions.
//
// This class ensures that the "void*" context value passed to |fidl_bind|
// is the same value used to dispatch to member functions.
template <typename T>
struct Binder {
  // Bind a member of a base class to a FIDL dispatch function, to allow
  // compatibility with the C bindings.
  //
  // For example FIDL functions:
  //
  //   1: MyFunction(Args) -> (ReturnValue);
  //   2: MyNonReturning(Args);
  //
  // The following C signatures will be generated by the FIDL compiler, and are expected in a
  // server's dispatch table that wishes to implement this interface:
  //
  //   zx_status_t MyFunction(void* ctx, Args... args, fidl_txn_t* txn);
  //   zx_status_t MyNonReturning(void* ctx, Args... args);
  //
  // This functionality can be implemented with this helper like so:
  //
  //   class MyClass {
  //   public:
  //       zx_status_t FunctionImplementation(Args... args, fidl_txn_t* txn) { ... }
  //       zx_status_t NonReturningImplementation(Args... args) { ... }
  //   };
  //
  //   fidl_MyInterface_ops_t ops = {
  //       .MyFunction = Binder<MyClass>::BindMember<&MyClass::FunctionImplementation>,
  //       .MyNonReturning = Binder<MyClass>::BindMember<&MyClass::NonReturningImplementation>,
  //   };
  //
  // Which will instantiate functions with signatures matching the auto-generated "My*Function"
  // C bindings, that automatically invoke the *FunctionImplementation member functions, using a
  // "MyClass" instance as context.
  template <auto Fn, typename... Args>
  static zx_status_t BindMember(Args... args) {
    auto memfn = std::mem_fn(Fn);
    return BindInternal(memfn, args...);
  }

  // Bind a disambiguated, overloaded member of a base class to a FIDL dispatch function, to allow
  // compatibility with the C bindings.
  //
  // For a FIDL function:
  //
  //   1: MyFunction(Args) -> (ReturnValue);
  //
  // The following C signature will be generated by the FIDL compiler, and is expected in a
  // server's dispatch table that wishes to implement this interface:
  //
  //   zx_status_t MyFunction(void* ctx, Args... args, fidl_txn_t* txn);
  //
  // This functionality can be implemented with this helper like so:
  //
  //   class MyClass {
  //   public:
  //       zx_status_t FunctionOverloaded(Args... args, fidl_txn_t* txn) { ... }
  //       zx_status_t FunctionOverloaded(OtherArgs... other_args);
  //   };
  //
  //   fidl_MyInterface_ops_t ops = {
  //       .MyFunction = Binder<MyClass>::BindMember<zx_status_t(Args..., fidl_txn_t*),
  //                                                 &MyClass::FunctionOverloaded>
  //   };
  //
  // Which will instantiate a function with a signature matching the auto-generated "MyFunction"
  // C binding, that automatically invokes the FunctionOverloaded member function matching the
  // specified signature, using a "MyClass" instance as context.
  template <typename FnSig, FnSig T::*Fn, typename... Args>
  static zx_status_t BindMember(Args... args) {
    auto memfn = std::mem_fn<FnSig, T>(Fn);
    return BindInternal(memfn, args...);
  }

  // A utility function which simplifies binding methods of derived methods to FIDL
  // dispatch functions.
  //
  // A typical use case would look like the following:
  //
  // FIDL:
  //
  //   1: MyFunction(Args) -> (ReturnValue);
  //
  // C++:
  //
  //   class MyClass {
  //   public:
  //       zx_status_t FunctionImplementation(Args... args, fidl_txn_t* txn) {
  //           ...;
  //       }
  //
  //       zx_status_t Bind(async_dispatcher_t* dispatcher, zx::channel channel) {
  //           static constexpr Interface_ops_t kOps = {
  //               .MyFunction = Binder<MyClass>::BindMember<&MyClass::FunctionImplementation>,
  //           };
  //           return Binder<MyClass>::BindOps<Dispatch>(dispatcher, channel, this, &kOps);
  //       }
  //   }
  //
  //   ...
  //
  //   MyClass instance;
  //   instance.Bind(dispatcher, channel);
  template <auto Dispatch, typename Ops>
  static zx_status_t BindOps(async_dispatcher_t* dispatcher, zx::channel channel, T* ctx,
                             const Ops* ops) {
    static_assert(
        std::is_same<decltype(Dispatch), zx_status_t (*)(void*, fidl_txn_t*, fidl_incoming_msg_t*,
                                                         const Ops* ops)>::value,
        "Invalid dispatch function");
    return fidl_bind(dispatcher, channel.release(), reinterpret_cast<fidl_dispatch_t*>(Dispatch),
                     ctx, ops);
  }

 private:
  template <typename MemFn, typename... Args>
  static zx_status_t BindInternal(MemFn memfn, void* ctx, Args... args) {
    auto instance = static_cast<T*>(ctx);
    return memfn(instance, args...);
  }
};

// Wrapper class around |fidl_async_txn_t|. This allows a transaction to be
// initialized, moved, reset, and completed without unintentionally "double completing"
// or "forgetting to complete".
class AsyncTransaction {
 public:
  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(AsyncTransaction);

  AsyncTransaction() : txn_(nullptr) {}
  explicit AsyncTransaction(fidl_txn_t* txn) : txn_(fidl_async_txn_create(txn)) {}
  explicit AsyncTransaction(AsyncTransaction&& other) : txn_(other.release()) {}
  AsyncTransaction& operator=(AsyncTransaction&& other) {
    Reinitialize(other.release());
    return *this;
  }

  ~AsyncTransaction() { Reinitialize(); }

  // Acquires a reference to the |fidl_txn_t| backing this txn object.
  // This reference will be invalidated if any non-const operations are called
  // on |AsyncTransaction|.
  //
  // Should not be called if the underlying transaction is invalid.
  fidl_txn_t* Transaction() const {
    ZX_DEBUG_ASSERT(HasTransaction());
    return fidl_async_txn_borrow(txn_);
  }

  // Completes the transaction and rebinds the underlying channel against the binding.
  //
  // Causes the transaction to become invalid.
  //
  // Should not be called if the underlying transaction is invalid.
  zx_status_t Rebind() {
    ZX_DEBUG_ASSERT(HasTransaction());
    return fidl_async_txn_complete(release(), true);
  }

  // Completes the current transaction, if one exists, and causes |AsyncTransaction| to
  // track a new |txn|.
  //
  // If |txn| is nullptr, this function causes the underlying transaction to become invalid.
  void Reset(fidl_txn_t* txn = nullptr) {
    fidl_async_txn_t* async_txn = txn ? fidl_async_txn_create(txn) : nullptr;
    Reinitialize(async_txn);
  }

 private:
  bool HasTransaction() const { return txn_ != nullptr; }

  __attribute__((warn_unused_result)) fidl_async_txn_t* release() {
    fidl_async_txn_t* txn = txn_;
    txn_ = nullptr;
    return txn;
  }

  void Reinitialize(fidl_async_txn_t* txn = nullptr) {
    if (HasTransaction()) {
      fidl_async_txn_complete(release(), false);
    }
    txn_ = txn;
  }

  fidl_async_txn_t* txn_;
};

}  // namespace fidl

#endif  // LIB_FIDL_UTILS_BIND_H_
