/*
 * Copyright 2015 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.
 */

#ifndef FOLLY_EXCEPTIONWRAPPER_H
#define FOLLY_EXCEPTIONWRAPPER_H

#include <cassert>
#include <exception>
#include <memory>
#include <folly/String.h>
#include <folly/detail/ExceptionWrapper.h>

namespace folly {

/*
 * Throwing exceptions can be a convenient way to handle errors. Storing
 * exceptions in an exception_ptr makes it easy to handle exceptions in a
 * different thread or at a later time. exception_ptr can also be used in a very
 * generic result/exception wrapper.
 *
 * However, there are some issues with throwing exceptions and
 * std::exception_ptr. These issues revolve around throw being expensive,
 * particularly in a multithreaded environment (see
 * ExceptionWrapperBenchmark.cpp).
 *
 * Imagine we have a library that has an API which returns a result/exception
 * wrapper. Let's consider some approaches for implementing this wrapper.
 * First, we could store a std::exception. This approach loses the derived
 * exception type, which can make exception handling more difficult for users
 * that prefer rethrowing the exception. We could use a folly::dynamic for every
 * possible type of exception. This is not very flexible - adding new types of
 * exceptions requires a change to the result/exception wrapper. We could use an
 * exception_ptr. However, constructing an exception_ptr as well as accessing
 * the error requires a call to throw. That means that there will be two calls
 * to throw in order to process the exception. For performance sensitive
 * applications, this may be unacceptable.
 *
 * exception_wrapper is designed to handle exception management for both
 * convenience and high performance use cases. make_exception_wrapper is
 * templated on derived type, allowing us to rethrow the exception properly for
 * users that prefer convenience. These explicitly named exception types can
 * therefore be handled without any peformance penalty.  exception_wrapper is
 * also flexible enough to accept any type. If a caught exception is not of an
 * explicitly named type, then std::exception_ptr is used to preserve the
 * exception state. For performance sensitive applications, the accessor methods
 * can test or extract a pointer to a specific exception type with very little
 * overhead.
 *
 * Example usage:
 *
 * exception_wrapper globalExceptionWrapper;
 *
 * // Thread1
 * void doSomethingCrazy() {
 *   int rc = doSomethingCrazyWithLameReturnCodes();
 *   if (rc == NAILED_IT) {
 *     globalExceptionWrapper = exception_wrapper();
 *   } else if (rc == FACE_PLANT) {
 *     globalExceptionWrapper = make_exception_wrapper<FacePlantException>();
 *   } else if (rc == FAIL_WHALE) {
 *     globalExceptionWrapper = make_exception_wrapper<FailWhaleException>();
 *   }
 * }
 *
 * // Thread2: Exceptions are ok!
 * void processResult() {
 *   try {
 *     globalExceptionWrapper.throwException();
 *   } catch (const FacePlantException& e) {
 *     LOG(ERROR) << "FACEPLANT!";
 *   } catch (const FailWhaleException& e) {
 *     LOG(ERROR) << "FAILWHALE!";
 *   }
 * }
 *
 * // Thread2: Exceptions are bad!
 * void processResult() {
 *   auto ep = globalExceptionWrapper.get();
 *   if (!ep.with_exception<FacePlantException>([&](
 *     FacePlantException& faceplant) {
 *       LOG(ERROR) << "FACEPLANT";
 *     })) {
 *     ep.with_exception<FailWhaleException>([&](
 *       FailWhaleException& failwhale) {
 *         LOG(ERROR) << "FAILWHALE!";
 *       });
 *   }
 * }
 *
 */
class exception_wrapper {
 protected:
  template <typename Ex>
  struct optimize;

 public:
  exception_wrapper() = default;

  // Implicitly construct an exception_wrapper from a qualifying exception.
  // See the optimize struct for details.
  template <typename Ex, typename =
    typename std::enable_if<optimize<typename std::decay<Ex>::type>::value>
    ::type>
  /* implicit */ exception_wrapper(Ex&& exn) {
    typedef typename std::decay<Ex>::type DEx;
    item_ = std::make_shared<DEx>(std::forward<Ex>(exn));
    throwfn_ = folly::detail::Thrower<DEx>::doThrow;
  }

  // The following two constructors are meant to emulate the behavior of
  // try_and_catch in performance sensitive code as well as to be flexible
  // enough to wrap exceptions of unknown type. There is an overload that
  // takes an exception reference so that the wrapper can extract and store
  // the exception's type and what() when possible.
  //
  // The canonical use case is to construct an all-catching exception wrapper
  // with minimal overhead like so:
  //
  //   try {
  //     // some throwing code
  //   } catch (const std::exception& e) {
  //     // won't lose e's type and what()
  //     exception_wrapper ew{std::current_exception(), e};
  //   } catch (...) {
  //     // everything else
  //     exception_wrapper ew{std::current_exception()};
  //   }
  //
  // try_and_catch is cleaner and preferable. Use it unless you're sure you need
  // something like this instead.
  template <typename Ex>
  explicit exception_wrapper(std::exception_ptr eptr, Ex& exn) {
    assign_eptr(eptr, exn);
  }

  explicit exception_wrapper(std::exception_ptr eptr) {
    assign_eptr(eptr);
  }

  void throwException() const {
    if (throwfn_) {
      throwfn_(item_.get());
    } else if (eptr_) {
      std::rethrow_exception(eptr_);
    }
  }

  explicit operator bool() const {
    return item_ || eptr_;
  }

  // This implementation is similar to std::exception_ptr's implementation
  // where two exception_wrappers are equal when the address in the underlying
  // reference field both point to the same exception object.  The reference
  // field remains the same when the exception_wrapper is copied or when
  // the exception_wrapper is "rethrown".
  bool operator==(const exception_wrapper& a) const {
    if (item_) {
      return a.item_ && item_.get() == a.item_.get();
    } else {
      return eptr_ == a.eptr_;
    }
  }

  bool operator!=(const exception_wrapper& a) const {
    return !(*this == a);
  }

  // This will return a non-nullptr only if the exception is held as a
  // copy.  It is the only interface which will distinguish between an
  // exception held this way, and by exception_ptr.  You probably
  // shouldn't use it at all.
  std::exception* getCopied() { return item_.get(); }
  const std::exception* getCopied() const { return item_.get(); }

  fbstring what() const {
    if (item_) {
      return exceptionStr(*item_);
    } else if (eptr_) {
      return estr_;
    } else {
      return fbstring();
    }
  }

  fbstring class_name() const {
    if (item_) {
      auto& i = *item_;
      return demangle(typeid(i));
    } else if (eptr_) {
      return ename_;
    } else {
      return fbstring();
    }
  }

  template <class Ex>
  bool is_compatible_with() const {
    if (item_) {
      return dynamic_cast<const Ex*>(item_.get());
    } else if (eptr_) {
      try {
        std::rethrow_exception(eptr_);
      } catch (std::exception& e) {
        return dynamic_cast<const Ex*>(&e);
      } catch (...) {
        // fall through
      }
    }
    return false;
  }

  // If this exception wrapper wraps an exception of type Ex, with_exception
  // will call f with the wrapped exception as an argument and return true, and
  // will otherwise return false.
  template <class Ex, class F>
  typename std::enable_if<
    std::is_base_of<std::exception, typename std::decay<Ex>::type>::value,
    bool>::type
  with_exception(F f) {
    return with_exception1<typename std::decay<Ex>::type>(f, this);
  }

  // Const overload
  template <class Ex, class F>
  typename std::enable_if<
    std::is_base_of<std::exception, typename std::decay<Ex>::type>::value,
    bool>::type
  with_exception(F f) const {
    return with_exception1<const typename std::decay<Ex>::type>(f, this);
  }

  // Overload for non-exceptions. Always rethrows.
  template <class Ex, class F>
  typename std::enable_if<
    !std::is_base_of<std::exception, typename std::decay<Ex>::type>::value,
    bool>::type
  with_exception(F f) const {
    try {
      throwException();
    } catch (typename std::decay<Ex>::type& e) {
      f(e);
      return true;
    } catch (...) {
      // fall through
    }
    return false;
  }

  std::exception_ptr getExceptionPtr() const {
    if (eptr_) {
      return eptr_;
    }

    try {
      throwException();
    } catch (...) {
      return std::current_exception();
    }
    return std::exception_ptr();
  }

protected:
  template <typename Ex>
  struct optimize {
    static const bool value =
      std::is_base_of<std::exception, Ex>::value &&
      std::is_copy_assignable<Ex>::value &&
      !std::is_abstract<Ex>::value;
  };

  template <typename Ex>
  void assign_eptr(std::exception_ptr eptr, Ex& e) {
    this->eptr_ = eptr;
    this->estr_ = exceptionStr(e).toStdString();
    this->ename_ = demangle(typeid(e)).toStdString();
  }

  void assign_eptr(std::exception_ptr eptr) {
    this->eptr_ = eptr;
  }

  // Optimized case: if we know what type the exception is, we can
  // store a copy of the concrete type, and a helper function so we
  // can rethrow it.
  std::shared_ptr<std::exception> item_;
  void (*throwfn_)(std::exception*){nullptr};
  // Fallback case: store the library wrapper, which is less efficient
  // but gets the job done.  Also store exceptionPtr() the name of the
  // exception type, so we can at least get those back out without
  // having to rethrow.
  std::exception_ptr eptr_;
  std::string estr_;
  std::string ename_;

  template <class T, class... Args>
  friend exception_wrapper make_exception_wrapper(Args&&... args);

private:
  // What makes this useful is that T can be exception_wrapper* or
  // const exception_wrapper*, and the compiler will use the
  // instantiation which works with F.
  template <class Ex, class F, class T>
  static bool with_exception1(F f, T* that) {
    if (that->item_) {
      if (auto ex = dynamic_cast<Ex*>(that->item_.get())) {
        f(*ex);
        return true;
      }
    } else if (that->eptr_) {
      try {
        std::rethrow_exception(that->eptr_);
      } catch (std::exception& e) {
        if (auto ex = dynamic_cast<Ex*>(&e)) {
          f(*ex);
          return true;
        }
      } catch (...) {
        // fall through
      }
    }
    return false;
  }
};

template <class T, class... Args>
exception_wrapper make_exception_wrapper(Args&&... args) {
  exception_wrapper ew;
  ew.item_ = std::make_shared<T>(std::forward<Args>(args)...);
  ew.throwfn_ = folly::detail::Thrower<T>::doThrow;
  return ew;
}

// For consistency with exceptionStr() functions in String.h
inline fbstring exceptionStr(const exception_wrapper& ew) {
  return ew.what();
}

/*
 * try_and_catch is a simple replacement for try {} catch(){} that allows you to
 * specify which derived exceptions you would like to catch and store in an
 * exception_wrapper.
 *
 * Because we cannot build an equivalent of std::current_exception(), we need
 * to catch every derived exception that we are interested in catching.
 *
 * Exceptions should be listed in the reverse order that you would write your
 * catch statements (that is, std::exception& should be first).
 *
 * NOTE: Although implemented as a derived class (for syntactic delight), don't
 * be confused - you should not pass around try_and_catch objects!
 *
 * Example Usage:
 *
 * // This catches my runtime_error and if I call throwException() on ew, it
 * // will throw a runtime_error
 * auto ew = folly::try_and_catch<std::exception, std::runtime_error>([=]() {
 *   if (badThingHappens()) {
 *     throw std::runtime_error("ZOMG!");
 *   }
 * });
 *
 * // This will catch the exception and if I call throwException() on ew, it
 * // will throw a std::exception
 * auto ew = folly::try_and_catch<std::exception, std::runtime_error>([=]() {
 *   if (badThingHappens()) {
 *     throw std::exception();
 *   }
 * });
 *
 * // This will not catch the exception and it will be thrown.
 * auto ew = folly::try_and_catch<std::runtime_error>([=]() {
 *   if (badThingHappens()) {
 *     throw std::exception();
 *   }
 * });
 */

template <typename... Exceptions>
class try_and_catch;

template <typename LastException, typename... Exceptions>
class try_and_catch<LastException, Exceptions...> :
    public try_and_catch<Exceptions...> {
 public:
  template <typename F>
  explicit try_and_catch(F&& fn) : Base() {
    call_fn(fn);
  }

 protected:
  typedef try_and_catch<Exceptions...> Base;

  try_and_catch() : Base() {}

  template <typename Ex>
  typename std::enable_if<!exception_wrapper::optimize<Ex>::value>::type
  assign_exception(Ex& e, std::exception_ptr eptr) {
    exception_wrapper::assign_eptr(eptr, e);
  }

  template <typename Ex>
  typename std::enable_if<exception_wrapper::optimize<Ex>::value>::type
  assign_exception(Ex& e, std::exception_ptr /*eptr*/) {
    this->item_ = std::make_shared<Ex>(e);
    this->throwfn_ = folly::detail::Thrower<Ex>::doThrow;
  }

  template <typename F>
  void call_fn(F&& fn) {
    try {
      Base::call_fn(std::move(fn));
    } catch (LastException& e) {
      if (typeid(e) == typeid(LastException&)) {
        assign_exception(e, std::current_exception());
      } else {
        exception_wrapper::assign_eptr(std::current_exception(), e);
      }
    }
  }
};

template<>
class try_and_catch<> : public exception_wrapper {
 public:
  try_and_catch() = default;

 protected:
  template <typename F>
  void call_fn(F&& fn) {
    fn();
  }
};
}
#endif
