IDBResult.h (5302B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef mozilla_dom_indexeddb_idbresult_h__ 6 #define mozilla_dom_indexeddb_idbresult_h__ 7 8 #include <type_traits> 9 #include <utility> 10 11 #include "mozilla/ErrorResult.h" 12 #include "mozilla/ResultVariant.h" 13 #include "mozilla/Variant.h" 14 15 namespace mozilla::dom::indexedDB { 16 17 // IDBSpecialValue represents two special return values, distinct from any other 18 // value, used in several places in the IndexedDB spec. 19 enum class IDBSpecialValue { 20 Failure, 21 Invalid, 22 }; 23 24 namespace detail { 25 26 template <IDBSpecialValue Value> 27 using SpecialConstant = std::integral_constant<IDBSpecialValue, Value>; 28 using FailureType = SpecialConstant<IDBSpecialValue::Failure>; 29 using InvalidType = SpecialConstant<IDBSpecialValue::Invalid>; 30 struct ExceptionType final {}; 31 } // namespace detail 32 33 // Put these in a subnamespace to avoid conflicts from the combination of 1. 34 // using namespace mozilla::dom::indexedDB; in cpp files, 2. the unified build 35 // and 3. mozilla::dom::Exception 36 namespace SpecialValues { 37 constexpr const detail::FailureType Failure; 38 constexpr const detail::InvalidType Invalid; 39 constexpr const detail::ExceptionType Exception; 40 } // namespace SpecialValues 41 42 namespace detail { 43 template <IDBSpecialValue... Elements> 44 struct IsSortedSet; 45 46 template <IDBSpecialValue First, IDBSpecialValue Second, 47 IDBSpecialValue... Rest> 48 struct IsSortedSet<First, Second, Rest...> 49 : std::conjunction<IsSortedSet<First, Second>, 50 IsSortedSet<Second, Rest...>> {}; 51 52 template <IDBSpecialValue First, IDBSpecialValue Second> 53 struct IsSortedSet<First, Second> : std::bool_constant<(First < Second)> {}; 54 55 template <IDBSpecialValue First> 56 struct IsSortedSet<First> : std::true_type {}; 57 58 template <> 59 struct IsSortedSet<> : std::true_type {}; 60 61 template <IDBSpecialValue... S> 62 class IDBError { 63 // This assertion ensures that permutations of the set of possible special 64 // values don't create distinct types. 65 static_assert(IsSortedSet<S...>::value, 66 "special value list must be sorted and unique"); 67 68 template <IDBSpecialValue... U> 69 friend class IDBError; 70 71 public: 72 MOZ_IMPLICIT IDBError(nsresult aRv) : mVariant(ErrorResult{aRv}) {} 73 74 IDBError(ExceptionType, ErrorResult&& aErrorResult) 75 : mVariant(std::move(aErrorResult)) {} 76 77 template <IDBSpecialValue Special> 78 MOZ_IMPLICIT IDBError(SpecialConstant<Special>) 79 : mVariant(SpecialConstant<Special>{}) {} 80 81 IDBError(IDBError&&) = default; 82 IDBError& operator=(IDBError&&) = default; 83 84 // Construct an IDBResult from another IDBResult whose set of possible special 85 // values is a subset of this one's. 86 template <IDBSpecialValue... U> 87 MOZ_IMPLICIT IDBError(IDBError<U...>&& aOther) 88 : mVariant(aOther.mVariant.match( 89 [](auto& aVariant) { return VariantType{std::move(aVariant)}; })) {} 90 91 bool Is(ExceptionType) const { return mVariant.template is<ErrorResult>(); } 92 93 template <IDBSpecialValue Special> 94 bool Is(SpecialConstant<Special>) const { 95 return mVariant.template is<SpecialConstant<Special>>(); 96 } 97 98 ErrorResult& AsException() { return mVariant.template as<ErrorResult>(); } 99 100 template <typename... SpecialValueMappers> 101 ErrorResult ExtractErrorResult(SpecialValueMappers... aSpecialValueMappers) { 102 #if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 8) 103 return mVariant.match( 104 [](ErrorResult& aException) { return std::move(aException); }, 105 [aSpecialValueMappers](const SpecialConstant<S>& aSpecialValue) { 106 return ErrorResult{aSpecialValueMappers(aSpecialValue)}; 107 }...); 108 #else 109 // gcc 7 doesn't accept the kind of parameter pack expansion above, 110 // probably due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226 111 return mVariant.match([aSpecialValueMappers...](auto& aValue) { 112 if constexpr (std::is_same_v<ErrorResult&, decltype(aValue)>) { 113 return std::move(aValue); 114 } else { 115 return ErrorResult{aSpecialValueMappers(aValue)...}; 116 } 117 }); 118 #endif 119 } 120 121 template <typename... SpecialValueMappers> 122 nsresult ExtractNSResult(SpecialValueMappers... aSpecialValueMappers) { 123 return mVariant.match( 124 [](ErrorResult& aException) { return aException.StealNSResult(); }, 125 aSpecialValueMappers...); 126 } 127 128 protected: 129 using VariantType = Variant<ErrorResult, SpecialConstant<S>...>; 130 131 VariantType mVariant; 132 }; 133 } // namespace detail 134 135 // Represents a return value of an IndexedDB algorithm. T is the type of the 136 // regular return value, while S is a list of special values that can be 137 // returned by the particular algorithm. 138 template <typename T, IDBSpecialValue... S> 139 using IDBResult = Result<T, detail::IDBError<S...>>; 140 141 template <nsresult E> 142 nsresult InvalidMapsTo(const indexedDB::detail::InvalidType&) { 143 return E; 144 } 145 146 inline detail::IDBError<> IDBException(nsresult aRv) { 147 return {SpecialValues::Exception, ErrorResult{aRv}}; 148 } 149 150 template <IDBSpecialValue Special> 151 detail::IDBError<Special> IDBError(detail::SpecialConstant<Special> aResult) { 152 return {aResult}; 153 } 154 155 } // namespace mozilla::dom::indexedDB 156 157 #endif // mozilla_dom_indexeddb_idbresult_h__