/*
 * Copyright 2017-present Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *
 * Author: Eric Niebler <eniebler@fb.com>
 */

#include <folly/Portability.h>

namespace folly {

template <class Fn>
struct exception_wrapper::arg_type_
    : public arg_type_<decltype(&Fn::operator())> {
};
template <class Ret, class Class, class Arg>
struct exception_wrapper::arg_type_<Ret (Class::*)(Arg)> {
  using type = Arg;
};
template <class Ret, class Class, class Arg>
struct exception_wrapper::arg_type_<Ret (Class::*)(Arg) const> {
  using type = Arg;
};
template <class Ret, class Arg>
struct exception_wrapper::arg_type_<Ret (Arg)> {
  using type = Arg;
};
template <class Ret, class Arg>
struct exception_wrapper::arg_type_<Ret (*)(Arg)> {
  using type = Arg;
};
template <class Ret, class Class>
struct exception_wrapper::arg_type_<Ret (Class::*)(...)> {
  using type = AnyException;
};
template <class Ret, class Class>
struct exception_wrapper::arg_type_<Ret (Class::*)(...) const> {
  using type = AnyException;
};
template <class Ret>
struct exception_wrapper::arg_type_<Ret (...)> {
  using type = AnyException;
};
template <class Ret>
struct exception_wrapper::arg_type_<Ret (*)(...)> {
  using type = AnyException;
};

template <class Ret, class... Args>
inline Ret exception_wrapper::noop_(Args...) {
  return Ret();
}

inline std::type_info const* exception_wrapper::uninit_type_(
    exception_wrapper const*) {
  return &typeid(void);
}

template <class Ex, typename... As>
inline exception_wrapper::Buffer::Buffer(in_place_type_t<Ex>, As&&... as_) {
  ::new (static_cast<void*>(&buff_)) Ex(std::forward<As>(as_)...);
}

template <class Ex>
inline Ex& exception_wrapper::Buffer::as() noexcept {
  return *static_cast<Ex*>(static_cast<void*>(&buff_));
}
template <class Ex>
inline Ex const& exception_wrapper::Buffer::as() const noexcept {
  return *static_cast<Ex const*>(static_cast<void const*>(&buff_));
}

inline std::exception const* exception_wrapper::as_exception_or_null_(
    std::exception const& ex) {
  return &ex;
}
inline std::exception const* exception_wrapper::as_exception_or_null_(
    AnyException) {
  return nullptr;
}

static_assert(
    !kIsWindows || sizeof(void*) == 8,
    "exception_wrapper is untested on 32 bit Windows.");
static_assert(
    !kIsWindows || (kMscVer >= 1900 && kMscVer <= 2000),
    "exception_wrapper is untested and possibly broken on your version of "
    "MSVC");

inline std::uintptr_t exception_wrapper::ExceptionPtr::as_int_(
    std::exception_ptr const& ptr,
    std::exception const& e) {
  if (!kIsWindows) {
    return reinterpret_cast<std::uintptr_t>(&e);
  } else {
    // On Windows, as of MSVC2017, all thrown exceptions are copied to the stack
    // first. Thus, we cannot depend on exception references associated with an
    // exception_ptr to be live for the duration of the exception_ptr. We need
    // to directly access the heap allocated memory inside the exception_ptr.
    //
    // std::exception_ptr is an opaque reinterpret_cast of
    // std::shared_ptr<__ExceptionPtr>
    // __ExceptionPtr is a non-virtual class with two members, a union and a
    // bool. The union contains the now-undocumented EHExceptionRecord, which
    // contains a struct which contains a void* which points to the heap
    // allocated exception.
    // We derive the offset to pExceptionObject via manual means.
    FOLLY_PACK_PUSH
    struct Win32ExceptionPtr {
      char offset[40];
      void* exceptionObject;
    } FOLLY_PACK_ATTR;
    FOLLY_PACK_POP

    auto* win32ExceptionPtr =
        reinterpret_cast<std::shared_ptr<Win32ExceptionPtr> const*>(
            &ptr)->get();
    return reinterpret_cast<std::uintptr_t>(win32ExceptionPtr->exceptionObject);
  }
}
inline std::uintptr_t exception_wrapper::ExceptionPtr::as_int_(
    std::exception_ptr const&,
    AnyException e) {
  return reinterpret_cast<std::uintptr_t>(e.typeinfo_) + 1;
}
inline bool exception_wrapper::ExceptionPtr::has_exception_() const {
  return 0 == exception_or_type_ % 2;
}
inline std::exception const* exception_wrapper::ExceptionPtr::as_exception_()
    const {
  return reinterpret_cast<std::exception const*>(exception_or_type_);
}
inline std::type_info const* exception_wrapper::ExceptionPtr::as_type_() const {
  return reinterpret_cast<std::type_info const*>(exception_or_type_ - 1);
}

inline void exception_wrapper::ExceptionPtr::copy_(
    exception_wrapper const* from, exception_wrapper* to) {
  ::new (static_cast<void*>(&to->eptr_)) ExceptionPtr(from->eptr_);
}
inline void exception_wrapper::ExceptionPtr::move_(
    exception_wrapper* from, exception_wrapper* to) {
  ::new (static_cast<void*>(&to->eptr_))
      ExceptionPtr(std::move(from->eptr_));
  delete_(from);
}
inline void exception_wrapper::ExceptionPtr::delete_(
    exception_wrapper* that) {
  that->eptr_.~ExceptionPtr();
  that->vptr_ = &uninit_;
}
[[noreturn]] inline void exception_wrapper::ExceptionPtr::throw_(
    exception_wrapper const* that) {
  std::rethrow_exception(that->eptr_.ptr_);
}
inline std::type_info const* exception_wrapper::ExceptionPtr::type_(
    exception_wrapper const* that) {
  if (auto e = get_exception_(that)) {
    return &typeid(*e);
  }
  return that->eptr_.as_type_();
}
inline std::exception const* exception_wrapper::ExceptionPtr::get_exception_(
    exception_wrapper const* that) {
  return that->eptr_.has_exception_() ? that->eptr_.as_exception_()
                                      : nullptr;
}
inline exception_wrapper exception_wrapper::ExceptionPtr::get_exception_ptr_(
    exception_wrapper const* that) {
  return *that;
}

template <class Ex>
inline void exception_wrapper::InPlace<Ex>::copy_(
    exception_wrapper const* from, exception_wrapper* to) {
  ::new (static_cast<void*>(std::addressof(to->buff_.as<Ex>())))
      Ex(from->buff_.as<Ex>());
}
template <class Ex>
inline void exception_wrapper::InPlace<Ex>::move_(
    exception_wrapper* from, exception_wrapper* to) {
  ::new (static_cast<void*>(std::addressof(to->buff_.as<Ex>())))
      Ex(std::move(from->buff_.as<Ex>()));
  delete_(from);
}
template <class Ex>
inline void exception_wrapper::InPlace<Ex>::delete_(
    exception_wrapper* that) {
  that->buff_.as<Ex>().~Ex();
  that->vptr_ = &uninit_;
}
template <class Ex>
[[noreturn]] inline void exception_wrapper::InPlace<Ex>::throw_(
    exception_wrapper const* that) {
  throw that->buff_.as<Ex>(); // @nolint
}
template <class Ex>
inline std::type_info const* exception_wrapper::InPlace<Ex>::type_(
    exception_wrapper const*) {
  return &typeid(Ex);
}
template <class Ex>
inline std::exception const* exception_wrapper::InPlace<Ex>::get_exception_(
    exception_wrapper const* that) {
  return as_exception_or_null_(that->buff_.as<Ex>());
}
template <class Ex>
inline exception_wrapper exception_wrapper::InPlace<Ex>::get_exception_ptr_(
    exception_wrapper const* that) {
  try {
    throw_(that);
  } catch (Ex const& ex) {
    return exception_wrapper{std::current_exception(), ex};
  }
}

template <class Ex>
[[noreturn]] inline void
exception_wrapper::SharedPtr::Impl<Ex>::throw_() const {
  throw ex_; // @nolint
}
template <class Ex>
inline std::exception const*
exception_wrapper::SharedPtr::Impl<Ex>::get_exception_() const noexcept {
  return as_exception_or_null_(ex_);
}
template <class Ex>
inline exception_wrapper
exception_wrapper::SharedPtr::Impl<Ex>::get_exception_ptr_() const noexcept {
  try {
    throw_();
  } catch (Ex& ex) {
    return exception_wrapper{std::current_exception(), ex};
  }
}
inline void exception_wrapper::SharedPtr::copy_(
    exception_wrapper const* from, exception_wrapper* to) {
  ::new (static_cast<void*>(std::addressof(to->sptr_)))
      SharedPtr(from->sptr_);
}
inline void exception_wrapper::SharedPtr::move_(
    exception_wrapper* from, exception_wrapper* to) {
  ::new (static_cast<void*>(std::addressof(to->sptr_)))
      SharedPtr(std::move(from->sptr_));
  delete_(from);
}
inline void exception_wrapper::SharedPtr::delete_(
    exception_wrapper* that) {
  that->sptr_.~SharedPtr();
  that->vptr_ = &uninit_;
}
[[noreturn]] inline void exception_wrapper::SharedPtr::throw_(
    exception_wrapper const* that) {
  that->sptr_.ptr_->throw_();
  folly::assume_unreachable();
}
inline std::type_info const* exception_wrapper::SharedPtr::type_(
    exception_wrapper const* that) {
  return that->sptr_.ptr_->info_;
}
inline std::exception const* exception_wrapper::SharedPtr::get_exception_(
    exception_wrapper const* that) {
  return that->sptr_.ptr_->get_exception_();
}
inline exception_wrapper exception_wrapper::SharedPtr::get_exception_ptr_(
    exception_wrapper const* that) {
  return that->sptr_.ptr_->get_exception_ptr_();
}

template <class Ex, typename... As>
inline exception_wrapper::exception_wrapper(OnHeapTag, in_place_type_t<Ex>, As&&... as)
    : sptr_{std::make_shared<SharedPtr::Impl<Ex>>(std::forward<As>(as)...)},
      vptr_(&SharedPtr::ops_) {}

template <class Ex, typename... As>
inline exception_wrapper::exception_wrapper(InSituTag, in_place_type_t<Ex>, As&&... as)
    : buff_{in_place_type<Ex>, std::forward<As>(as)...},
      vptr_(&InPlace<Ex>::ops_) {}

inline exception_wrapper::exception_wrapper(exception_wrapper&& that) noexcept
    : exception_wrapper{} {
  (vptr_ = that.vptr_)->move_(&that, this); // Move into *this, won't throw
}

inline exception_wrapper::exception_wrapper(
    exception_wrapper const& that) : exception_wrapper{} {
  that.vptr_->copy_(&that, this); // could throw
  vptr_ = that.vptr_;
}

// If `this == &that`, this move assignment operator leaves the object in a
// valid but unspecified state.
inline exception_wrapper& exception_wrapper::operator=(
    exception_wrapper&& that) noexcept {
  vptr_->delete_(this); // Free the current exception
  (vptr_ = that.vptr_)->move_(&that, this); // Move into *this, won't throw
  return *this;
}

inline exception_wrapper& exception_wrapper::operator=(
    exception_wrapper const& that) {
  exception_wrapper(that).swap(*this);
  return *this;
}

inline exception_wrapper::~exception_wrapper() {
  reset();
}

template <class Ex>
inline exception_wrapper::exception_wrapper(std::exception_ptr ptr, Ex& ex)
    : eptr_{ptr, ExceptionPtr::as_int_(ptr, ex)},
      vptr_(&ExceptionPtr::ops_) {
  assert(eptr_.ptr_);
}

namespace exception_wrapper_detail {
template <class Ex>
Ex&& dont_slice(Ex&& ex) {
  assert(typeid(ex) == typeid(_t<std::decay<Ex>>) ||
       !"Dynamic and static exception types don't match. Exception would "
        "be sliced when storing in exception_wrapper.");
  return std::forward<Ex>(ex);
}
}

template <
    class Ex,
    class Ex_,
    FOLLY_REQUIRES_DEF(
        Conjunction<
            exception_wrapper::IsStdException<Ex_>,
            exception_wrapper::IsRegularExceptionType<Ex_>>::value)>
inline exception_wrapper::exception_wrapper(Ex&& ex)
    : exception_wrapper{
        PlacementOf<Ex_>{},
        in_place_type<Ex_>,
        exception_wrapper_detail::dont_slice(std::forward<Ex>(ex))} {
}

template <
    class Ex,
    class Ex_,
    FOLLY_REQUIRES_DEF(
        exception_wrapper::IsRegularExceptionType<Ex_>::value)>
inline exception_wrapper::exception_wrapper(in_place_t, Ex&& ex)
    : exception_wrapper{
        PlacementOf<Ex_>{},
        in_place_type<Ex_>,
        exception_wrapper_detail::dont_slice(std::forward<Ex>(ex))} {
}

template <
    class Ex,
    typename... As,
    FOLLY_REQUIRES_DEF(
        exception_wrapper::IsRegularExceptionType<Ex>::value)>
inline exception_wrapper::exception_wrapper(in_place_type_t<Ex>, As&&... as)
    : exception_wrapper{
        PlacementOf<Ex>{},
        in_place_type<Ex>,
        std::forward<As>(as)...} {
}

inline void exception_wrapper::swap(exception_wrapper& that) noexcept {
  exception_wrapper tmp(std::move(that));
  that = std::move(*this);
  *this = std::move(tmp);
}

inline exception_wrapper::operator bool() const noexcept {
  return vptr_ != &uninit_;
}

inline bool exception_wrapper::operator!() const noexcept {
  return !static_cast<bool>(*this);
}

inline void exception_wrapper::reset() {
  vptr_->delete_(this);
}

inline bool exception_wrapper::has_exception_ptr() const noexcept {
  return vptr_ == &ExceptionPtr::ops_;
}

inline std::exception* exception_wrapper::get_exception() noexcept {
  return const_cast<std::exception*>(vptr_->get_exception_(this));
}
inline std::exception const* exception_wrapper::get_exception() const noexcept {
  return vptr_->get_exception_(this);
}

template <typename Ex>
inline Ex* exception_wrapper::get_exception() noexcept {
  Ex* object{nullptr};
  with_exception([&](Ex& ex) { object = &ex; });
  return object;
}

template <typename Ex>
inline Ex const* exception_wrapper::get_exception() const noexcept {
  Ex const* object{nullptr};
  with_exception([&](Ex const& ex) { object = &ex; });
  return object;
}

inline std::exception_ptr const& exception_wrapper::to_exception_ptr()
    noexcept {
  // Computing an exception_ptr is expensive so cache the result.
  return (*this = vptr_->get_exception_ptr_(this)).eptr_.ptr_;
}
inline std::exception_ptr exception_wrapper::to_exception_ptr() const noexcept {
  return vptr_->get_exception_ptr_(this).eptr_.ptr_;
}

inline std::type_info const& exception_wrapper::none() noexcept {
  return typeid(void);
}
inline std::type_info const& exception_wrapper::unknown() noexcept {
  return typeid(Unknown);
}

inline std::type_info const& exception_wrapper::type() const noexcept {
  return *vptr_->type_(this);
}

inline folly::fbstring exception_wrapper::what() const {
  if (auto e = get_exception()) {
    return class_name() + ": " + e->what();
  }
  return class_name();
}

inline folly::fbstring exception_wrapper::class_name() const {
  auto& ti = type();
  return ti == none()
      ? ""
      : ti == unknown() ? "<unknown exception>" : folly::demangle(ti);
}

template <class Ex>
inline bool exception_wrapper::is_compatible_with() const noexcept {
  return with_exception([](Ex const&) {});
}

[[noreturn]] inline void exception_wrapper::throw_exception() const {
  vptr_->throw_(this);
  onNoExceptionError(__func__);
}

template <class CatchFn, bool IsConst>
struct exception_wrapper::ExceptionTypeOf {
  using type = arg_type<_t<std::decay<CatchFn>>>;
  static_assert(
      std::is_reference<type>::value,
      "Always catch exceptions by reference.");
  static_assert(
      !IsConst || std::is_const<_t<std::remove_reference<type>>>::value,
      "handle() or with_exception() called on a const exception_wrapper "
      "and asked to catch a non-const exception. Handler will never fire. "
      "Catch exception by const reference to fix this.");
};

// Nests a throw in the proper try/catch blocks
template <bool IsConst>
struct exception_wrapper::HandleReduce {
  bool* handled_;

  template <
      class ThrowFn,
      class CatchFn,
      FOLLY_REQUIRES(!IsCatchAll<CatchFn>::value)>
  auto operator()(ThrowFn&& th, CatchFn& ca) const {
    using Ex = _t<ExceptionTypeOf<CatchFn, IsConst>>;
    return [ th = std::forward<ThrowFn>(th), &ca, handled_ = handled_ ] {
      try {
        th();
      } catch (Ex& e) {
        // If we got here because a catch function threw, rethrow.
        if (*handled_) {
          throw;
        }
        *handled_ = true;
        ca(e);
      }
    };
  }

  template <
      class ThrowFn,
      class CatchFn,
      FOLLY_REQUIRES(IsCatchAll<CatchFn>::value)>
  auto operator()(ThrowFn&& th, CatchFn& ca) const {
    return [ th = std::forward<ThrowFn>(th), &ca, handled_ = handled_ ] {
      try {
        th();
      } catch (...) {
        // If we got here because a catch function threw, rethrow.
        if (*handled_) {
          throw;
        }
        *handled_ = true;
        ca();
      }
    };
  }
};

// When all the handlers expect types derived from std::exception, we can
// sometimes invoke the handlers without throwing any exceptions.
template <bool IsConst>
struct exception_wrapper::HandleStdExceptReduce {
  using StdEx = AddConstIf<IsConst, std::exception>;

  template <
      class ThrowFn,
      class CatchFn,
      FOLLY_REQUIRES(!IsCatchAll<CatchFn>::value)>
  auto operator()(ThrowFn&& th, CatchFn& ca) const {
    using Ex = _t<ExceptionTypeOf<CatchFn, IsConst>>;
    return [ th = std::forward<ThrowFn>(th), &ca ](auto&& continuation)
        -> StdEx* {
      if (auto e = const_cast<StdEx*>(th(continuation))) {
        if (auto e2 = dynamic_cast<_t<std::add_pointer<Ex>>>(e)) {
          ca(*e2);
        } else {
          return e;
        }
      }
      return nullptr;
    };
  }

  template <
      class ThrowFn,
      class CatchFn,
      FOLLY_REQUIRES(IsCatchAll<CatchFn>::value)>
  auto operator()(ThrowFn&& th, CatchFn& ca) const {
    return [ th = std::forward<ThrowFn>(th), &ca ](auto&&) -> StdEx* {
      // The following continuation causes ca() to execute if *this contains
      // an exception /not/ derived from std::exception.
      auto continuation = [&ca](StdEx* e) {
        return e != nullptr ? e : ((void)ca(), nullptr);
      };
      if (th(continuation) != nullptr) {
        ca();
      }
      return nullptr;
    };
  }
};

// Called when some types in the catch clauses are not derived from
// std::exception.
template <class This, class... CatchFns>
inline void exception_wrapper::handle_(
    std::false_type, This& this_, CatchFns&... fns) {
  bool handled = false;
  auto impl = exception_wrapper_detail::fold(
      HandleReduce<std::is_const<This>::value>{&handled},
      [&] { this_.throw_exception(); },
      fns...);
  impl();
}

// Called when all types in the catch clauses are either derived from
// std::exception or a catch-all clause.
template <class This, class... CatchFns>
inline void exception_wrapper::handle_(
    std::true_type, This& this_, CatchFns&... fns) {
  using StdEx = exception_wrapper_detail::
      AddConstIf<std::is_const<This>::value, std::exception>;
  auto impl = exception_wrapper_detail::fold(
      HandleStdExceptReduce<std::is_const<This>::value>{},
      [&](auto&& continuation) {
        return continuation(
            const_cast<StdEx*>(this_.vptr_->get_exception_(&this_)));
      },
      fns...);
  // This continuation gets evaluated if CatchFns... does not include a
  // catch-all handler. It is a no-op.
  auto continuation = [](StdEx* ex) { return ex; };
  if (StdEx* e = impl(continuation)) {
    throw *e; // Not handled. Throw.
  }
}

namespace exception_wrapper_detail {
template <class Ex, class Fn>
struct catch_fn {
  Fn fn_;
  auto operator()(Ex& ex) {
    return fn_(ex);
  }
};

template <class Ex, class Fn>
inline catch_fn<Ex, Fn> catch_(Ex*, Fn fn) {
  return {std::move(fn)};
}
template <class Fn>
inline Fn catch_(void const*, Fn fn) {
  return fn;
}
} // namespace exception_wrapper_detail

template <class Ex, class This, class Fn>
inline bool exception_wrapper::with_exception_(This& this_, Fn fn_) {
  if (!this_) {
    return false;
  }
  bool handled = true;
  auto fn = exception_wrapper_detail::catch_(
      static_cast<Ex*>(nullptr), std::move(fn_));
  auto&& all = [&](...) { handled = false; };
  handle_(IsStdException<arg_type<decltype(fn)>>{}, this_, fn, all);
  return handled;
}

template <class Ex, class Fn>
inline bool exception_wrapper::with_exception(Fn fn) {
  return with_exception_<Ex>(*this, std::move(fn));
}
template <class Ex, class Fn>
inline bool exception_wrapper::with_exception(Fn fn) const {
  return with_exception_<Ex const>(*this, std::move(fn));
}

template <class... CatchFns>
inline void exception_wrapper::handle(CatchFns... fns) {
  using AllStdEx =
      exception_wrapper_detail::AllOf<IsStdException, arg_type<CatchFns>...>;
  if (!*this) {
    onNoExceptionError(__func__);
  }
  this->handle_(AllStdEx{}, *this, fns...);
}
template <class... CatchFns>
inline void exception_wrapper::handle(CatchFns... fns) const {
  using AllStdEx =
      exception_wrapper_detail::AllOf<IsStdException, arg_type<CatchFns>...>;
  if (!*this) {
    onNoExceptionError(__func__);
  }
  this->handle_(AllStdEx{}, *this, fns...);
}

} // namespace folly
