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>
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
{
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
{};
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
43 template <IDBSpecialValue
... Elements
>
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
{};
60 struct IsSortedSet
<> : std::true_type
{};
62 template <IDBSpecialValue
... S
>
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
;
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
)};
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
);
116 return ErrorResult
{aSpecialValueMappers(aValue
)...};
122 template <typename
... SpecialValueMappers
>
123 nsresult
ExtractNSResult(SpecialValueMappers
... aSpecialValueMappers
) {
124 return mVariant
.match(
125 [](ErrorResult
& aException
) { return aException
.StealNSResult(); },
126 aSpecialValueMappers
...);
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
&) {
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
) {
156 } // namespace mozilla::dom::indexedDB
158 #endif // mozilla_dom_indexeddb_idbresult_h__