/*
 *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef RTC_BASE_FUNCTION_H_
#define RTC_BASE_FUNCTION_H_

#include <memory>
#include <type_traits>
#include <utility>

#include "rtc_base/system/assume.h"

namespace webrtc {
namespace webrtc_function_impl {

using FunVoid = void();

union VoidUnion {
  void* void_ptr;
  FunVoid* fun_ptr;
  typename std::aligned_storage<16>::type inline_storage;
};

template <typename T>
struct CallHelpers;
template <typename RetT, typename... ArgT>
struct CallHelpers<RetT(ArgT...)> {
  using return_type = RetT;
  template <typename F>
  static RetT CallVoidPtr(VoidUnion* vu, ArgT... args) {
    return (*static_cast<F*>(vu->void_ptr))(std::forward<ArgT>(args)...);
  }
  static RetT CallFunPtr(VoidUnion* vu, ArgT... args) {
    return (reinterpret_cast<RetT (*)(ArgT...)>(vu->fun_ptr))(
        std::forward<ArgT>(args)...);
  }
  template <typename F>
  static RetT CallInlineStorage(VoidUnion* vu, ArgT... args) {
    return (*reinterpret_cast<F*>(&vu->inline_storage))(
        std::forward<ArgT>(args)...);
  }
  static RetT DoCall(FunVoid* f, VoidUnion* vu, ArgT... args) {
    return reinterpret_cast<RetT (*)(VoidUnion*, ArgT...)>(f)(
        vu, std::forward<ArgT>(args)...);
  }
};

}  // namespace webrtc_function_impl

// A class that holds (and owns) any callable. The same function call signature
// must be provided when constructing and calling the object.
//
// The point of not having the call signature as a class template parameter is
// to have one single concrete type for all signatures; this reduces binary
// size.
class UntypedFunction final {
 public:
  // Create function for lambdas and other callables; it accepts every type of
  // argument except those noted in its enable_if call.
  template <
      typename Signature,
      typename F,
      typename std::enable_if<
          // Not for function pointers; we have another overload for that below.
          !std::is_function<typename std::remove_pointer<
              typename std::remove_reference<F>::type>::type>::value &&

          // Not for nullptr; we have another overload for that below.
          !std::is_same<std::nullptr_t,
                        typename std::remove_cv<F>::type>::value &&

          // Not for UntypedFunction objects; we have another overload for that.
          !std::is_same<UntypedFunction,
                        typename std::remove_cv<typename std::remove_reference<
                            F>::type>::type>::value>::type* = nullptr>
  static UntypedFunction Create(F&& f) {
    using F_deref = typename std::remove_reference<F>::type;
    // TODO(C++17): Use `constexpr if` here. The compiler appears to do the
    // right thing anyway w.r.t. resolving the branch statically and
    // eliminating dead code, but it would be good for readability.
    if (std::is_trivially_move_constructible<F_deref>::value &&
        std::is_trivially_destructible<F_deref>::value &&
        sizeof(F_deref) <=
            sizeof(webrtc_function_impl::VoidUnion::inline_storage)) {
      // The callable is trivial and small enough, so we just store its bytes
      // in the inline storage.
      webrtc_function_impl::VoidUnion vu;
      new (&vu.inline_storage) F_deref(std::forward<F>(f));
      return UntypedFunction(
          vu,
          reinterpret_cast<webrtc_function_impl::FunVoid*>(
              webrtc_function_impl::CallHelpers<
                  Signature>::template CallInlineStorage<F_deref>),
          nullptr);
    } else {
      // The callable is either nontrivial or too large, so we can't keep it
      // in the inline storage; use the heap instead.
      webrtc_function_impl::VoidUnion vu;
      vu.void_ptr = new F_deref(std::forward<F>(f));
      return UntypedFunction(
          vu,
          reinterpret_cast<webrtc_function_impl::FunVoid*>(
              webrtc_function_impl::CallHelpers<
                  Signature>::template CallVoidPtr<F_deref>),
          static_cast<void (*)(webrtc_function_impl::VoidUnion*)>(
              [](webrtc_function_impl::VoidUnion* vu) {
                // Assuming that this pointer isn't null allows the
                // compiler to eliminate a null check in the (inlined)
                // delete operation.
                RTC_ASSUME(vu->void_ptr != nullptr);
                delete reinterpret_cast<F_deref*>(vu->void_ptr);
              }));
    }
  }

  // Create function that accepts function pointers. If the argument is null,
  // the result is an empty UntypedFunction.
  template <typename Signature>
  static UntypedFunction Create(Signature* f) {
    webrtc_function_impl::VoidUnion vu;
    vu.fun_ptr = reinterpret_cast<webrtc_function_impl::FunVoid*>(f);
    return UntypedFunction(
        vu,
        f ? reinterpret_cast<webrtc_function_impl::FunVoid*>(
                webrtc_function_impl::CallHelpers<Signature>::CallFunPtr)
          : nullptr,
        nullptr);
  }

  // Default constructor. Creates an empty UntypedFunction.
  UntypedFunction() : call_(nullptr), delete_(nullptr) {}

  // Nullptr constructor and assignment. Creates an empty UntypedFunction.
  UntypedFunction(std::nullptr_t)  // NOLINT(runtime/explicit)
      : call_(nullptr), delete_(nullptr) {}
  UntypedFunction& operator=(std::nullptr_t) {
    call_ = nullptr;
    if (delete_) {
      delete_(&f_);
      delete_ = nullptr;
    }
    return *this;
  }

  // Not copyable.
  UntypedFunction(const UntypedFunction&) = delete;
  UntypedFunction& operator=(const UntypedFunction&) = delete;

  // Move construction and assignment.
  UntypedFunction(UntypedFunction&& other)
      : f_(other.f_), call_(other.call_), delete_(other.delete_) {
    other.delete_ = nullptr;
  }
  UntypedFunction& operator=(UntypedFunction&& other) {
    if (delete_) {
      delete_(&f_);
    }
    f_ = other.f_;
    call_ = other.call_;
    delete_ = other.delete_;
    other.delete_ = nullptr;
    return *this;
  }

  ~UntypedFunction() {
    if (delete_) {
      delete_(&f_);
    }
  }

  friend void swap(UntypedFunction& a, UntypedFunction& b) {
    using std::swap;
    swap(a.f_, b.f_);
    swap(a.call_, b.call_);
    swap(a.delete_, b.delete_);
  }

  // Returns true if we have a function, false if we don't (i.e., we're null).
  explicit operator bool() const { return call_ != nullptr; }

  template <typename Signature, typename... ArgT>
  typename webrtc_function_impl::CallHelpers<Signature>::return_type Call(
      ArgT&&... args) {
    return webrtc_function_impl::CallHelpers<Signature>::DoCall(
        call_, &f_, std::forward<ArgT>(args)...);
  }

  // Returns true iff we don't need to call a destructor. This is guaranteed
  // to hold for a moved-from object.
  bool IsTriviallyDestructible() { return delete_ == nullptr; }

 private:
  UntypedFunction(webrtc_function_impl::VoidUnion f,
                  webrtc_function_impl::FunVoid* call,
                  void (*del)(webrtc_function_impl::VoidUnion*))
      : f_(f), call_(call), delete_(del) {}

  // The callable thing, or a pointer to it.
  webrtc_function_impl::VoidUnion f_;

  // Pointer to a dispatch function that knows the type of the callable thing
  // that's stored in f_, and how to call it. An UntypedFunction object is empty
  // (null) iff call_ is null.
  webrtc_function_impl::FunVoid* call_;

  // Pointer to a function that knows how to delete the callable thing that's
  // stored in f_. Null if `f_` is trivially deletable.
  void (*delete_)(webrtc_function_impl::VoidUnion*);
};

}  // namespace webrtc

#endif  // RTC_BASE_FUNCTION_H_
