Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / indexedDB / IDBResult.h
blob424eda9bff1206f8a7d9a16f12ca2867d22c4544
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/. */
5 #ifndef mozilla_dom_indexeddb_idbresult_h__
6 #define mozilla_dom_indexeddb_idbresult_h__
8 #include "mozilla/ErrorResult.h"
9 #include "mozilla/ResultVariant.h"
10 #include "mozilla/Variant.h"
12 #include <type_traits>
13 #include <utility>
15 namespace mozilla::dom::indexedDB {
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,
24 namespace detail {
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
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
42 namespace detail {
43 template <IDBSpecialValue... Elements>
44 struct IsSortedSet;
46 template <IDBSpecialValue First, IDBSpecialValue Second,
47 IDBSpecialValue... Rest>
48 struct IsSortedSet<First, Second, Rest...>
49 : std::integral_constant<bool, IsSortedSet<First, Second>::value &&
50 IsSortedSet<Second, Rest...>::value> {};
52 template <IDBSpecialValue First, IDBSpecialValue Second>
53 struct IsSortedSet<First, Second>
54 : std::integral_constant<bool, (First < Second)> {};
56 template <IDBSpecialValue First>
57 struct IsSortedSet<First> : std::true_type {};
59 template <>
60 struct IsSortedSet<> : std::true_type {};
62 template <IDBSpecialValue... S>
63 class IDBError {
64 // This assertion ensures that permutations of the set of possible special
65 // values don't create distinct types.
66 static_assert(IsSortedSet<S...>::value,
67 "special value list must be sorted and unique");
69 template <IDBSpecialValue... U>
70 friend class IDBError;
72 public:
73 MOZ_IMPLICIT IDBError(nsresult aRv) : mVariant(ErrorResult{aRv}) {}
75 IDBError(ExceptionType, ErrorResult&& aErrorResult)
76 : mVariant(std::move(aErrorResult)) {}
78 template <IDBSpecialValue Special>
79 MOZ_IMPLICIT IDBError(SpecialConstant<Special>)
80 : mVariant(SpecialConstant<Special>{}) {}
82 IDBError(IDBError&&) = default;
83 IDBError& operator=(IDBError&&) = default;
85 // Construct an IDBResult from another IDBResult whose set of possible special
86 // values is a subset of this one's.
87 template <IDBSpecialValue... U>
88 MOZ_IMPLICIT IDBError(IDBError<U...>&& aOther)
89 : mVariant(aOther.mVariant.match(
90 [](auto& aVariant) { return VariantType{std::move(aVariant)}; })) {}
92 bool Is(ExceptionType) const { return mVariant.template is<ErrorResult>(); }
94 template <IDBSpecialValue Special>
95 bool Is(SpecialConstant<Special>) const {
96 return mVariant.template is<SpecialConstant<Special>>();
99 ErrorResult& AsException() { return mVariant.template as<ErrorResult>(); }
101 template <typename... SpecialValueMappers>
102 ErrorResult ExtractErrorResult(SpecialValueMappers... aSpecialValueMappers) {
103 #if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 8)
104 return mVariant.match(
105 [](ErrorResult& aException) { return std::move(aException); },
106 [aSpecialValueMappers](const SpecialConstant<S>& aSpecialValue) {
107 return ErrorResult{aSpecialValueMappers(aSpecialValue)};
108 }...);
109 #else
110 // gcc 7 doesn't accept the kind of parameter pack expansion above,
111 // probably due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226
112 return mVariant.match([aSpecialValueMappers...](auto& aValue) {
113 if constexpr (std::is_same_v<ErrorResult&, decltype(aValue)>) {
114 return std::move(aValue);
115 } else {
116 return ErrorResult{aSpecialValueMappers(aValue)...};
119 #endif
122 template <typename... SpecialValueMappers>
123 nsresult ExtractNSResult(SpecialValueMappers... aSpecialValueMappers) {
124 return mVariant.match(
125 [](ErrorResult& aException) { return aException.StealNSResult(); },
126 aSpecialValueMappers...);
129 protected:
130 using VariantType = Variant<ErrorResult, SpecialConstant<S>...>;
132 VariantType mVariant;
134 } // namespace detail
136 // Represents a return value of an IndexedDB algorithm. T is the type of the
137 // regular return value, while S is a list of special values that can be
138 // returned by the particular algorithm.
139 template <typename T, IDBSpecialValue... S>
140 using IDBResult = Result<T, detail::IDBError<S...>>;
142 template <nsresult E>
143 nsresult InvalidMapsTo(const indexedDB::detail::InvalidType&) {
144 return E;
147 inline detail::IDBError<> IDBException(nsresult aRv) {
148 return {SpecialValues::Exception, ErrorResult{aRv}};
151 template <IDBSpecialValue Special>
152 detail::IDBError<Special> IDBError(detail::SpecialConstant<Special> aResult) {
153 return {aResult};
156 } // namespace mozilla::dom::indexedDB
158 #endif // mozilla_dom_indexeddb_idbresult_h__