DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (c68fe15a81fc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_indexeddb_idbresult_h__
#define mozilla_dom_indexeddb_idbresult_h__

#include <mozilla/ErrorResult.h>
#include <mozilla/Variant.h>

#include <type_traits>
#include <utility>

namespace mozilla {
namespace dom {
namespace indexedDB {

// IDBSpecialValue represents two special return values, distinct from any other
// value, used in several places in the IndexedDB spec.
enum class IDBSpecialValue {
  Failure,
  Invalid,
};

namespace detail {
template <typename T>
struct OkType final {
  T mValue;
};

template <>
struct OkType<void> final {};

template <IDBSpecialValue Value>
using SpecialConstant = std::integral_constant<IDBSpecialValue, Value>;
using FailureType = SpecialConstant<IDBSpecialValue::Failure>;
using InvalidType = SpecialConstant<IDBSpecialValue::Invalid>;
struct ExceptionType final {};
struct VoidType final {};
}  // namespace detail

namespace {
template <typename T>
constexpr inline detail::OkType<std::remove_reference_t<T>> Ok(T&& aValue) {
  return {std::forward<T>(aValue)};
}

constexpr inline detail::OkType<void> Ok() { return {}; }

constexpr const detail::FailureType Failure;
constexpr const detail::InvalidType Invalid;
constexpr const detail::ExceptionType Exception;
}  // namespace

namespace detail {
template <IDBSpecialValue... Elements>
struct IsSortedSet;

template <IDBSpecialValue First, IDBSpecialValue Second,
          IDBSpecialValue... Rest>
struct IsSortedSet<First, Second, Rest...>
    : std::integral_constant<bool, IsSortedSet<First, Second>::value &&
                                       IsSortedSet<Second, Rest...>::value> {};

template <IDBSpecialValue First, IDBSpecialValue Second>
struct IsSortedSet<First, Second>
    : std::integral_constant<bool, (First < Second)> {};

template <IDBSpecialValue First>
struct IsSortedSet<First> : std::true_type {};

template <>
struct IsSortedSet<> : std::true_type {};

// IDBResultBase contains the bulk of the implementation of IDBResult, namely
// functionality that's applicable to all values of T.
template <typename T, IDBSpecialValue... S>
class IDBResultBase {
  // This assertion ensures that permutations of the set of possible special
  // values don't create distinct types.
  static_assert(IsSortedSet<S...>::value,
                "special value list must be sorted and unique");

  template <typename R, IDBSpecialValue... U>
  friend class IDBResultBase;

 protected:
  using ValueType = OkType<T>;

 public:
  // Construct a normal result. Use the Ok function to create an object of type
  // ValueType.
  MOZ_IMPLICIT IDBResultBase(const ValueType& aValue) : mVariant(aValue) {}

  MOZ_IMPLICIT IDBResultBase(ExceptionType) : mVariant(ExceptionType{}) {}

  template <IDBSpecialValue Special>
  MOZ_IMPLICIT IDBResultBase(SpecialConstant<Special>)
      : mVariant(SpecialConstant<Special>{}) {}

  // Construct an IDBResult from another IDBResult whose set of possible special
  // values is a subset of this one's.
  template <IDBSpecialValue... U>
  MOZ_IMPLICIT IDBResultBase(const IDBResultBase<T, U...>& aOther)
      : mVariant(aOther.mVariant.match(
            [](auto& aVariant) { return VariantType{aVariant}; })) {}

  // Test whether the result is a normal return value. The choice of the first
  // parameter's type makes it possible to write `result.Is(Ok, rv)`, promoting
  // readability and uniformity with other functions in the overload set.
  bool Is(OkType<void> (*)(), const ErrorResult& aRv) const {
    AssertConsistency(aRv);
    return mVariant.template is<ValueType>();
  }

  bool Is(ExceptionType, const ErrorResult& aRv) const {
    AssertConsistency(aRv);
    return mVariant.template is<ExceptionType>();
  }

  template <IDBSpecialValue Special>
  bool Is(SpecialConstant<Special>, const ErrorResult& aRv) const {
    AssertConsistency(aRv);
    return mVariant.template is<SpecialConstant<Special>>();
  }

 protected:
  void AssertConsistency(const ErrorResult& aRv) const {
    MOZ_ASSERT(aRv.Failed() == mVariant.template is<ExceptionType>());
  }

  using VariantType = Variant<ValueType, ExceptionType, SpecialConstant<S>...>;

  VariantType mVariant;
};
}  // namespace detail

// Represents a return value of an IndexedDB algorithm. T is the type of the
// regular return value, while S is a list of special values that can be
// returned by the particular algorithm.
template <typename T, IDBSpecialValue... S>
class MOZ_MUST_USE_TYPE IDBResult : public detail::IDBResultBase<T, S...> {
 public:
  using IDBResult::IDBResultBase::IDBResultBase;

  // Get a reference to the regular return value, asserting that this object
  // is indeed a regular return value.
  T& Unwrap(const ErrorResult& aRv) {
    return const_cast<T&>(static_cast<const IDBResult*>(this)->Unwrap(aRv));
  }

  const T& Unwrap(const ErrorResult& aRv) const {
    this->AssertConsistency(aRv);
    return this->mVariant.template as<typename IDBResult::ValueType>().mValue;
  }
};

template <IDBSpecialValue... S>
class MOZ_MUST_USE_TYPE IDBResult<void, S...>
    : public detail::IDBResultBase<void, S...> {
 public:
  using IDBResult::IDBResultBase::IDBResultBase;
};

}  // namespace indexedDB
}  // namespace dom
}  // namespace mozilla

#endif  // mozilla_dom_indexeddb_idbresult_h__