Blame dom/indexedDB/IDBResult.h

Packit f0b94e
/* This Source Code Form is subject to the terms of the Mozilla Public
Packit f0b94e
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit f0b94e
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit f0b94e
Packit f0b94e
#ifndef mozilla_dom_indexeddb_idbresult_h__
Packit f0b94e
#define mozilla_dom_indexeddb_idbresult_h__
Packit f0b94e
Packit f0b94e
#include <mozilla/ErrorResult.h>
Packit f0b94e
#include <mozilla/Variant.h>
Packit f0b94e
Packit f0b94e
#include <type_traits>
Packit f0b94e
#include <utility>
Packit f0b94e
Packit f0b94e
namespace mozilla {
Packit f0b94e
namespace dom {
Packit f0b94e
namespace indexedDB {
Packit f0b94e
Packit f0b94e
// IDBSpecialValue represents two special return values, distinct from any other
Packit f0b94e
// value, used in several places in the IndexedDB spec.
Packit f0b94e
enum class IDBSpecialValue {
Packit f0b94e
  Failure,
Packit f0b94e
  Invalid,
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
namespace detail {
Packit f0b94e
template <typename T>
Packit f0b94e
struct OkType final {
Packit f0b94e
  T mValue;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
template <>
Packit f0b94e
struct OkType<void> final {};
Packit f0b94e
Packit f0b94e
template <IDBSpecialValue Value>
Packit f0b94e
using SpecialConstant = std::integral_constant<IDBSpecialValue, Value>;
Packit f0b94e
using FailureType = detail::SpecialConstant<IDBSpecialValue::Failure>;
Packit f0b94e
using InvalidType = detail::SpecialConstant<IDBSpecialValue::Invalid>;
Packit f0b94e
struct ExceptionType final {};
Packit f0b94e
struct VoidType final {};
Packit f0b94e
}  // namespace detail
Packit f0b94e
Packit f0b94e
namespace {
Packit f0b94e
template <typename T>
Packit f0b94e
constexpr inline detail::OkType<std::remove_reference_t<T>> Ok(T&& aValue) {
Packit f0b94e
  return {std::forward<T>(aValue)};
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
constexpr inline detail::OkType<void> Ok() { return {}; }
Packit f0b94e
Packit f0b94e
constexpr const detail::FailureType Failure;
Packit f0b94e
constexpr const detail::InvalidType Invalid;
Packit f0b94e
constexpr const detail::ExceptionType Exception;
Packit f0b94e
}  // namespace
Packit f0b94e
Packit f0b94e
namespace detail {
Packit f0b94e
template <IDBSpecialValue... Elements>
Packit f0b94e
struct IsSortedSet;
Packit f0b94e
Packit f0b94e
template 
Packit f0b94e
          IDBSpecialValue... Rest>
Packit f0b94e
struct IsSortedSet<First, Second, Rest...>
Packit f0b94e
    : std::integral_constant<bool, IsSortedSet<First, Second>::value &&
Packit f0b94e
                                       IsSortedSet<Second, Rest...>::value> {};
Packit f0b94e
Packit f0b94e
template <IDBSpecialValue First, IDBSpecialValue Second>
Packit f0b94e
struct IsSortedSet<First, Second>
Packit f0b94e
    : std::integral_constant<bool, (First < Second)> {};
Packit f0b94e
Packit f0b94e
template <IDBSpecialValue First>
Packit f0b94e
struct IsSortedSet<First> : std::true_type {};
Packit f0b94e
Packit f0b94e
template <>
Packit f0b94e
struct IsSortedSet<> : std::true_type {};
Packit f0b94e
Packit f0b94e
// IDBResultBase contains the bulk of the implementation of IDBResult, namely
Packit f0b94e
// functionality that's applicable to all values of T.
Packit f0b94e
template <typename T, IDBSpecialValue... S>
Packit f0b94e
class IDBResultBase {
Packit f0b94e
  // This assertion ensures that permutations of the set of possible special
Packit f0b94e
  // values don't create distinct types.
Packit f0b94e
  static_assert(detail::IsSortedSet<S...>::value,
Packit f0b94e
                "special value list must be sorted and unique");
Packit f0b94e
Packit f0b94e
  template <typename R, IDBSpecialValue... U>
Packit f0b94e
  friend class IDBResultBase;
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  using ValueType = detail::OkType<T>;
Packit f0b94e
Packit f0b94e
 public:
Packit f0b94e
  // Construct a normal result. Use the Ok function to create an object of type
Packit f0b94e
  // ValueType.
Packit f0b94e
  MOZ_IMPLICIT IDBResultBase(const ValueType& aValue) : mVariant(aValue) {}
Packit f0b94e
Packit f0b94e
  MOZ_IMPLICIT IDBResultBase(detail::ExceptionType)
Packit f0b94e
      : mVariant(detail::ExceptionType{}) {}
Packit f0b94e
Packit f0b94e
  template <IDBSpecialValue Special>
Packit f0b94e
  MOZ_IMPLICIT IDBResultBase(detail::SpecialConstant<Special>)
Packit f0b94e
      : mVariant(detail::SpecialConstant<Special>{}) {}
Packit f0b94e
Packit f0b94e
  using VariantType =
Packit f0b94e
      Variant<ValueType, detail::ExceptionType, detail::SpecialConstant<S>...>;
Packit f0b94e
Packit f0b94e
  struct Matcher {
Packit f0b94e
    template <typename V>
Packit f0b94e
    VariantType match(const V& aVariant) const {
Packit f0b94e
      return VariantType{aVariant};
Packit f0b94e
    };
Packit f0b94e
  };
Packit f0b94e
Packit f0b94e
  // Construct an IDBResult from another IDBResult whose set of possible special
Packit f0b94e
  // values is a subset of this one's.
Packit f0b94e
  template <IDBSpecialValue... U>
Packit f0b94e
  MOZ_IMPLICIT IDBResultBase(const IDBResultBase<T, U...>& aOther)
Packit f0b94e
     : mVariant(aOther.mVariant.match(Matcher())) {}
Packit f0b94e
Packit f0b94e
  // Test whether the result is a normal return value. The choice of the first
Packit f0b94e
  // parameter's type makes it possible to write `result.Is(Ok, rv)`, promoting
Packit f0b94e
  // readability and uniformity with other functions in the overload set.
Packit f0b94e
  bool Is(detail::OkType<void> (*)(), const ErrorResult& aRv) const {
Packit f0b94e
    AssertConsistency(aRv);
Packit f0b94e
    return mVariant.template is<ValueType>();
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  bool Is(detail::ExceptionType, const ErrorResult& aRv) const {
Packit f0b94e
    AssertConsistency(aRv);
Packit f0b94e
    return mVariant.template is<detail::ExceptionType>();
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  template <IDBSpecialValue Special>
Packit f0b94e
  bool Is(detail::SpecialConstant<Special>, const ErrorResult& aRv) const {
Packit f0b94e
    AssertConsistency(aRv);
Packit f0b94e
    return mVariant.template is<detail::SpecialConstant<Special>>();
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
 protected:
Packit f0b94e
  void AssertConsistency(const ErrorResult& aRv) const {
Packit f0b94e
    MOZ_ASSERT(aRv.Failed() == mVariant.template is<detail::ExceptionType>());
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  VariantType mVariant;
Packit f0b94e
};
Packit f0b94e
}  // namespace detail
Packit f0b94e
Packit f0b94e
// Represents a return value of an IndexedDB algorithm. T is the type of the
Packit f0b94e
// regular return value, while S is a list of special values that can be
Packit f0b94e
// returned by the particular algorithm.
Packit f0b94e
template <typename T, IDBSpecialValue... S>
Packit f0b94e
class MOZ_MUST_USE_TYPE IDBResult : public detail::IDBResultBase<T, S...> {
Packit f0b94e
 public:
Packit f0b94e
  using IDBResult::IDBResultBase::IDBResultBase;
Packit f0b94e
Packit f0b94e
  // Get a reference to the regular return value, asserting that this object
Packit f0b94e
  // is indeed a regular return value.
Packit f0b94e
  T& Unwrap(const ErrorResult& aRv) {
Packit f0b94e
    return const_cast<T&>(static_cast<const IDBResult*>(this)->Unwrap(aRv));
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  const T& Unwrap(const ErrorResult& aRv) const {
Packit f0b94e
    this->AssertConsistency(aRv);
Packit f0b94e
    return this->mVariant.template as<typename IDBResult::ValueType>().mValue;
Packit f0b94e
  }
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
template <IDBSpecialValue... S>
Packit f0b94e
class MOZ_MUST_USE_TYPE IDBResult<void, S...>
Packit f0b94e
    : public detail::IDBResultBase<void, S...> {
Packit f0b94e
 public:
Packit f0b94e
  using IDBResult::IDBResultBase::IDBResultBase;
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
}  // namespace indexedDB
Packit f0b94e
}  // namespace dom
Packit f0b94e
}  // namespace mozilla
Packit f0b94e
Packit f0b94e
#endif  // mozilla_dom_indexeddb_idbresult_h__